4using System.Threading.Tasks;
15 private readonly CancellationTokenSource[] cancelWaitSources;
16 private readonly CancellationTokenSource[] cancelWorkSources;
17 private readonly T[] currentWorkItem;
18 private readonly Task[] processors;
19 private readonly
string name;
20 private readonly
int nrProcessors;
21 private LinkedListNode<IAsyncProcessor> processorNode;
23 private int nrProcessorsRunning;
24 private bool terminating =
false;
25 private bool terminated =
false;
26 private bool idle =
true;
32 [Obsolete(
"Use the constructor with a Name argument.")]
34 : this(NrProcessors, Guid.NewGuid().ToString())
45 if (NrProcessors <= 0)
46 throw new ArgumentException(
"Number of processors must be positive.", nameof(NrProcessors));
51 this.nrProcessors = this.nrProcessorsRunning = NrProcessors;
52 this.processors =
new Task[NrProcessors];
54 this.cancelWaitSources =
new CancellationTokenSource[NrProcessors];
55 this.cancelWorkSources =
new CancellationTokenSource[NrProcessors];
56 this.currentWorkItem =
new T[NrProcessors];
59 for (i = 0; i < this.nrProcessors; i++)
60 this.processors[i] = this.PerformWork(i);
66 [Obsolete(
"Use the DisposeAsync() method.")]
77 this.terminating =
true;
79 if (!(this.processorNode is
null))
82 this.processorNode =
null;
87 for (
int i = 0; i < this.nrProcessors; i++)
89 this.cancelWaitSources[i]?.Cancel();
90 this.cancelWorkSources[i]?.Cancel();
93 await Task.WhenAll(this.processors);
94 this.terminated =
true;
132 this.terminating =
true;
134 for (
int i = 0; i < this.nrProcessors; i++)
135 this.cancelWaitSources[i]?.Cancel();
137 if (!this.terminated && Timeout > 0)
139 if (Timeout > 0 && Timeout <
int.MaxValue)
141 _ = Task.Delay(Timeout).ContinueWith((
_) =>
143 for (
int i = 0; i < this.nrProcessors; i++)
144 this.cancelWorkSources[i]?.Cancel();
148 if (WaitForCompletion)
149 await Task.WhenAll(this.processors);
151 this.terminated =
true;
167 if (!this.terminating)
170 this.queue?.
Queue(Work);
181 if (!this.terminating)
184 return this.queue?.
Forward(Work) ?? Task.FromResult(
false);
187 return Task.FromResult(
false);
193 public string Name => this.name;
219 private async Task PerformWork(
int ProcessorIndex)
229 if (this.terminating)
231 if (!(this.queue?.TryGetItem(out Item) ??
false))
236 using (CancellationTokenSource Cancel =
new CancellationTokenSource())
238 this.cancelWaitSources[ProcessorIndex] = Cancel;
241 Task = this.queue?.
Wait(Cancel.Token);
245 if (!Task.IsCompleted &&
this.queue.CountSubscribers ==
this.nrProcessors)
248 await this.
OnIdle.Raise(
this, e);
257 this.cancelWaitSources[ProcessorIndex] =
null;
264 using (CancellationTokenSource Cancel =
new CancellationTokenSource())
266 this.cancelWorkSources[ProcessorIndex] = Cancel;
267 this.currentWorkItem[ProcessorIndex] = Item;
270 await Item.Execute(Cancel.Token);
271 Item.Processed(!Cancel.IsCancellationRequested);
275 Item.Processed(
false);
280 this.cancelWorkSources[ProcessorIndex] =
null;
281 this.currentWorkItem[ProcessorIndex] =
default;
291 if (--this.nrProcessorsRunning == 0)
292 this.terminated =
true;
299 public event EventHandlerAsync<ProcessorEventArgs>
OnIdle;
306 TaskCompletionSource<bool>
Idle =
new TaskCompletionSource<bool>();
308 Task
OnIdle(
object Sender, EventArgs e)
310 Task.Run(() =>
Idle.TrySetResult(
true));
311 return Task.CompletedTask;
Static class managing the application event log. Applications and services log events on this static ...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Processes work tasks, in an asynchronous manner.
bool Terminating
If the console worker is being terminated.
void CloseForTermination()
Closes the processor for new items, but continues to process queued items.
void Dispose()
Stops processing tasks and disposes the queue.
bool Terminated
If the console worker has been terminated.
async Task DisposeAsync()
Stops processing tasks and disposes the queue.
Task CloseForTermination(bool WaitForCompletion)
Closes the processor for new items. If WaitForCompletion is true, the method waits for queued items ...
async Task WaitUntilIdle()
Waits until the processor becomes idle.
bool Idle
If processor is idle
AsyncProcessor(int NrProcessors)
Processes work tasks, in an asynchronous manner.
AsyncProcessor(int NrProcessors, string Name)
Processes work tasks, in an asynchronous manner.
string Name
Name of processor.
EventHandlerAsync< ProcessorEventArgs > OnIdle
Event raised when the processor becomes idle. It can be raised multiple times if more than one proces...
int QueueSize
Number of items in queue.
void Queue(T Work)
Queues a work item for processing. No information is returned wether the item was forwarded or discar...
Task< bool > Forward(T Work)
Forwards a work item for processing.
async Task CloseForTermination(bool WaitForCompletion, int Timeout)
Closes the processor for new items. If WaitForCompletion is true, the method waits for queued items ...
Maintains a record of active processors.
Asynchronous First-in-First-out (FIFO) Queue, for use when transporting items of type T between task...
Task< bool > Forward(T Item)
Processes an item by adding it last in the queue.
Task< T > Wait()
Waits indefinitely (or until queue is disposed) for an item to be available. If Queue is disposed,...
void Queue(T Item)
Queues an item for processing by adding it last in the queue. No information is returned wether the i...
void Dispose()
IDisposable.Dispose
int CountItems
Number of items in queue.
Event arguments for processor events.
Interface for AsyncProcessor<T> instances.
Interface for asynchronous operations.