4using System.Threading.Tasks;
16 private readonly LinkedList<TaskCompletionSource<object>> waitingDequeuers =
new LinkedList<TaskCompletionSource<object>>();
17 private readonly SemaphoreSlim semaphore;
19 private readonly
bool profiling;
20 private readonly
string queueName;
23 private bool disposed =
false;
43 this.profiling = !(this.profiler is
null);
44 this.semaphore =
new SemaphoreSlim(1);
48 this.enqueueThread = this.profiler.CreateThread(
"Enqueue(" + this.queueName +
")",
ProfilerThreadType.Binary);
49 this.dequeueThread = this.profiler.CreateThread(
"Dequeue(" + this.queueName +
")",
ProfilerThreadType.Binary);
51 this.enqueueThread.Start();
52 this.dequeueThread.Start();
56 this.enqueueThread =
null;
57 this.dequeueThread =
null;
72 await this.semaphore.WaitAsync();
75 return this.waitingDequeuers.Count;
79 this.semaphore.Release();
93 [Obsolete(
"Use DisposeAsync instead.")]
106 this.disposed =
true;
108 await this.semaphore.WaitAsync();
110 foreach (TaskCompletionSource<object> T
in this.waitingDequeuers)
111 T.TrySetResult(
null);
113 this.waitingDequeuers.Clear();
117 this.enqueueThread.Stop();
118 this.dequeueThread.Stop();
130 return this.
Enqueue(Item,
int.MaxValue);
139 public async Task<bool>
Enqueue(
object Item,
int TimeoutMilliseconds)
142 throw new ArgumentNullException(nameof(Item));
145 this.enqueueThread.High();
147 DateTime StartUtc = DateTime.UtcNow;
148 TaskCompletionSource<bool> Wait =
null;
156 this.enqueueThread.Low();
163 int Milliseconds = (int)(TimeoutMilliseconds - DateTime.UtcNow.Subtract(StartUtc).TotalMilliseconds);
164 if (Milliseconds < 0)
167 this.enqueueThread.Low();
172 _ = Task.Delay(Milliseconds).ContinueWith((
_) =>
174 Wait?.TrySetResult(
false);
175 return Task.CompletedTask;
178 if (!await Wait.Task ||
this.disposed)
181 this.enqueueThread.Low();
189 await this.semaphore.WaitAsync();
192 LinkedListNode<TaskCompletionSource<object>> First = this.waitingDequeuers.First;
199 CreatedUtc = DateTime.UtcNow,
208 this.waitingDequeuers.RemoveFirst();
209 Forwarded = First.Value.TrySetResult(Item);
214 this.semaphore.Release();
220 this.enqueueThread.Low();
234 return this.
Dequeue(
int.MaxValue,
true);
257 public Task<object>
Dequeue(
int TimeoutMilliseconds)
259 return this.
Dequeue(TimeoutMilliseconds,
true);
282 private async Task<object>
Dequeue(
int TimeoutMilliseconds,
bool RemoveItem)
284 if (TimeoutMilliseconds < 0)
285 throw new ArgumentOutOfRangeException(nameof(TimeoutMilliseconds),
"Value must be non-negative.");
291 this.dequeueThread.High();
293 bool Released =
false;
295 await this.semaphore.WaitAsync();
307 this.dequeueThread.Low();
314 QueuedItem Item = await
Database.FindFirstIgnoreRest<QueuedItem>(
321 this.dequeueThread.Low();
327 if (TimeoutMilliseconds == 0)
330 this.dequeueThread.Low();
335 TaskCompletionSource<object> Waiter =
new TaskCompletionSource<object>();
336 LinkedListNode<TaskCompletionSource<object>> Node = this.waitingDequeuers.AddLast(Waiter);
338 this.semaphore.Release();
341 _ = Task.Delay(TimeoutMilliseconds).ContinueWith(async (
_) =>
345 await this.semaphore.WaitAsync();
348 if (!(Node.List is
null))
349 this.waitingDequeuers.Remove(Node);
353 this.semaphore.Release();
356 Waiter.TrySetResult(
null);
364 object Result = await Waiter.Task;
368 QueuedItem QueuedItem =
new QueuedItem()
371 CreatedUtc = DateTime.UtcNow,
379 this.dequeueThread.Low();
386 this.semaphore.Release();
395 await this.semaphore.WaitAsync();
404 this.semaphore.Release();
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.
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static Task< IEnumerable< object > > FindDelete(string Collection, params string[] SortOrder)
Finds objects in a given collection and deletes them in the same atomic operation.
static async Task Delete(object Object)
Deletes an object in the database.
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
This filter selects objects that have a named field equal to a given value.
Queue persisted into the database.
void Dispose()
Disposes the connection
Task< int > GetNrEnqueuers()
Gets the number of enqueuers waiting for space to be available to enqueue new items.
Task< object > Peek()
Returns the next item available to be dequeued, without dequeueing it. If an item is not available,...
async Task< bool > Enqueue(object Item, int TimeoutMilliseconds)
Enqueues an item into the queue.
DatabaseQueue(string QueueName, Profiler Profiler)
Queue persisted into the database.
Task< object > Dequeue(int TimeoutMilliseconds)
Dequeue an item from the queue. The task will wait for an item to be dequeued, or,...
Task< object > Dequeue()
Dequeue an item from the queue. The task will wait for an item to be dequeued, or,...
async Task Clear()
Clears the queue.
Task< object > TryDequeue()
Tries to dequeue an item from the queue, if one exists. If an item is not available,...
string QueueName
Queue name.
Task< bool > Enqueue(object Item)
Enqueues an item into the queue.
DatabaseQueue(string QueueName)
Queue persisted into the database.
async Task DisposeAsync()
Disposes of the object, asynchronously.
async Task< int > GetNrDequeuers()
Gets the number of dequeuers waiting for items to be queued.
Represents one item in a queue.
object Content
Object content of item.
Class that keeps track of events and timing.
Class that keeps track of events and timing for one thread.
Inteface for persisted queues.
ProfilerThreadType
Type of profiler thread.