diff --git a/src/ZirconNet.Core/Async/QueueAsync.cs b/src/ZirconNet.Core/Async/QueueAsync.cs index 44c4287..921bff5 100644 --- a/src/ZirconNet.Core/Async/QueueAsync.cs +++ b/src/ZirconNet.Core/Async/QueueAsync.cs @@ -6,8 +6,9 @@ namespace ZirconNet.Core.Async; public sealed class QueueAsync { - private readonly SemaphoreSlim _semaphoreSlim; - private readonly ConcurrentQueue> _queuedActions = new(); + private readonly SemaphoreSlim _taskSemaphore; + private readonly SemaphoreSlim _queueSemaphore; + private int _tasksInQueue = 0; public QueueAsync(int maximumThreads = -1) { @@ -16,13 +17,14 @@ public QueueAsync(int maximumThreads = -1) maximumThreads = Environment.ProcessorCount; } - _semaphoreSlim = new SemaphoreSlim(maximumThreads); + _taskSemaphore = new SemaphoreSlim(maximumThreads); + _queueSemaphore = new SemaphoreSlim(1,1); } private async Task RunAction(Func actionToRun, CancellationToken cancellationToken) { - _queuedActions.Enqueue(actionToRun); - await _semaphoreSlim.WaitAsync(cancellationToken); + Interlocked.Increment(ref _tasksInQueue); + await _taskSemaphore.WaitAsync(cancellationToken); _ = Task.Run(async () => { @@ -32,19 +34,23 @@ private async Task RunAction(Func actionToRun, CancellationToken cancellat { await actionToRun.Invoke(); } + catch (Exception) + { + // Log or handle the exception as appropriate + } finally { - _semaphoreSlim.Release(); + Interlocked.Decrement(ref _tasksInQueue); + if (_tasksInQueue == 0) + { + _queueSemaphore.Release(); + } + _taskSemaphore.Release(); } } }, cancellationToken); } - /// - /// Add a task to the running queue. - /// - /// The current task to run. - /// Cancellation token public async Task AddTaskAsync(Func actionToRun, CancellationToken cancellationToken = default) { if (!cancellationToken.IsCancellationRequested) @@ -53,14 +59,8 @@ public async Task AddTaskAsync(Func actionToRun, CancellationToken cancell } } - /// - /// Wait for the current queued items to reach 0. - /// - public async Task WaitForQueueEnd() + public async Task WaitForQueueEnd(CancellationToken cancellationToken = default) { - while (_queuedActions.TryPeek(out _)) - { - await Task.Delay(10); - } + await _queueSemaphore.WaitAsync(cancellationToken); } -} +} \ No newline at end of file diff --git a/src/ZirconNet.WPF/Dispatcher/BufferedThreadDispatcher.cs b/src/ZirconNet.WPF/Dispatcher/BufferedThreadDispatcher.cs index 0181160..a25e200 100644 --- a/src/ZirconNet.WPF/Dispatcher/BufferedThreadDispatcher.cs +++ b/src/ZirconNet.WPF/Dispatcher/BufferedThreadDispatcher.cs @@ -11,7 +11,9 @@ public sealed class BufferedThreadDispatcher { public static BufferedThreadDispatcher Current { get; } = new(); - //Delay to wait between the screen refresh. + /// + /// Delay to wait between the screen refresh. + /// public int Delay { get; set; } = 40; private readonly int _mainThreadId;