Improve exception handling in AsyncQueue.

This commit is contained in:
Christian Kratky
2020-10-30 20:43:39 +01:00
parent 58ad599783
commit f773257c86
+35 -13
View File
@@ -7,15 +7,19 @@ namespace MQTTnet.Internal
{
public sealed class AsyncQueue<TItem> : IDisposable
{
readonly object _syncRoot = new object();
SemaphoreSlim _semaphore = new SemaphoreSlim(0);
ConcurrentQueue<TItem> _queue = new ConcurrentQueue<TItem>();
public int Count => _queue.Count;
public void Enqueue(TItem item)
{
_queue.Enqueue(item);
_semaphore?.Release();
lock (_syncRoot)
{
_queue.Enqueue(item);
_semaphore?.Release();
}
}
public async Task<AsyncQueueDequeueResult<TItem>> TryDequeueAsync(CancellationToken cancellationToken)
@@ -24,23 +28,38 @@ namespace MQTTnet.Internal
{
try
{
if (_semaphore == null)
Task task;
lock (_syncRoot)
{
if (_semaphore == null)
{
return new AsyncQueueDequeueResult<TItem>(false, default);
}
task = _semaphore.WaitAsync(cancellationToken);
}
await task.ConfigureAwait(false);
if (cancellationToken.IsCancellationRequested)
{
return new AsyncQueueDequeueResult<TItem>(false, default);
}
await _semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
cancellationToken.ThrowIfCancellationRequested();
if (_queue.TryDequeue(out var item))
{
return new AsyncQueueDequeueResult<TItem>(true, item);
}
}
catch (ArgumentNullException)
{
// The semaphore throws this internally sometimes.
return new AsyncQueueDequeueResult<TItem>(false, default);
}
catch (OperationCanceledException)
{
return new AsyncQueueDequeueResult<TItem>(false, default);
}
if (_queue.TryDequeue(out var item))
{
return new AsyncQueueDequeueResult<TItem>(true, item);
}
}
return new AsyncQueueDequeueResult<TItem>(false, default);
@@ -63,8 +82,11 @@ namespace MQTTnet.Internal
public void Dispose()
{
_semaphore?.Dispose();
_semaphore = null;
lock (_syncRoot)
{
_semaphore?.Dispose();
_semaphore = null;
}
}
}
}