mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-20 03:24:33 +08:00
1565 high cpu load from asyncsignal (#1566)
This commit is contained in:
@@ -29,7 +29,7 @@ namespace MQTTnet.Internal
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
_signal?.Dispose();
|
||||
_signal.Dispose();
|
||||
|
||||
_isDisposed = true;
|
||||
}
|
||||
@@ -48,10 +48,10 @@ namespace MQTTnet.Internal
|
||||
{
|
||||
if (_queue.TryDequeue(out var item))
|
||||
{
|
||||
return new AsyncQueueDequeueResult<TItem>(true, item);
|
||||
return AsyncQueueDequeueResult<TItem>.Success(item);
|
||||
}
|
||||
|
||||
return new AsyncQueueDequeueResult<TItem>(false, default);
|
||||
return AsyncQueueDequeueResult<TItem>.NonSuccess;
|
||||
}
|
||||
|
||||
public async Task<AsyncQueueDequeueResult<TItem>> TryDequeueAsync(CancellationToken cancellationToken)
|
||||
@@ -60,36 +60,42 @@ namespace MQTTnet.Internal
|
||||
{
|
||||
try
|
||||
{
|
||||
Task task;
|
||||
Task task = null;
|
||||
lock (_syncRoot)
|
||||
{
|
||||
if (_isDisposed)
|
||||
{
|
||||
return new AsyncQueueDequeueResult<TItem>(false, default);
|
||||
return AsyncQueueDequeueResult<TItem>.NonSuccess;
|
||||
}
|
||||
|
||||
task = _signal.WaitAsync(cancellationToken);
|
||||
if (_queue.IsEmpty)
|
||||
{
|
||||
task = _signal.WaitAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
await task.ConfigureAwait(false);
|
||||
|
||||
if (task != null)
|
||||
{
|
||||
await task.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return new AsyncQueueDequeueResult<TItem>(false, default);
|
||||
return AsyncQueueDequeueResult<TItem>.NonSuccess;
|
||||
}
|
||||
|
||||
if (_queue.TryDequeue(out var item))
|
||||
{
|
||||
return new AsyncQueueDequeueResult<TItem>(true, item);
|
||||
return AsyncQueueDequeueResult<TItem>.Success(item);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
return new AsyncQueueDequeueResult<TItem>(false, default);
|
||||
return AsyncQueueDequeueResult<TItem>.NonSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
return new AsyncQueueDequeueResult<TItem>(false, default);
|
||||
return AsyncQueueDequeueResult<TItem>.NonSuccess;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,10 @@
|
||||
|
||||
namespace MQTTnet.Internal
|
||||
{
|
||||
public class AsyncQueueDequeueResult<TItem>
|
||||
public sealed class AsyncQueueDequeueResult<TItem>
|
||||
{
|
||||
public static readonly AsyncQueueDequeueResult<TItem> NonSuccess = new AsyncQueueDequeueResult<TItem>(false, default);
|
||||
|
||||
public AsyncQueueDequeueResult(bool isSuccess, TItem item)
|
||||
{
|
||||
IsSuccess = isSuccess;
|
||||
@@ -15,5 +17,10 @@ namespace MQTTnet.Internal
|
||||
public bool IsSuccess { get; }
|
||||
|
||||
public TItem Item { get; }
|
||||
|
||||
public static AsyncQueueDequeueResult<TItem> Success(TItem item)
|
||||
{
|
||||
return new AsyncQueueDequeueResult<TItem>(true, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,9 +33,17 @@ namespace MQTTnet.Internal
|
||||
{
|
||||
_isSignaled = true;
|
||||
|
||||
Cleanup();
|
||||
|
||||
// If there is already a waiting task let it run.
|
||||
_waiter?.Approve();
|
||||
_waiter = null;
|
||||
if (_waiter != null)
|
||||
{
|
||||
_waiter.Approve();
|
||||
_waiter = null;
|
||||
|
||||
// Since we already got a waiter the signal must be reset right now!
|
||||
_isSignaled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +55,11 @@ namespace MQTTnet.Internal
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
Cleanup();
|
||||
|
||||
if (_isSignaled)
|
||||
{
|
||||
_isSignaled = false;
|
||||
return CompletedTask.Instance;
|
||||
}
|
||||
|
||||
@@ -58,7 +69,7 @@ namespace MQTTnet.Internal
|
||||
{
|
||||
throw new InvalidOperationException("Only one waiting task is permitted per async signal.");
|
||||
}
|
||||
|
||||
|
||||
_waiter.Dispose();
|
||||
}
|
||||
|
||||
@@ -67,6 +78,15 @@ namespace MQTTnet.Internal
|
||||
}
|
||||
}
|
||||
|
||||
void Cleanup()
|
||||
{
|
||||
// Cleanup if the previous waiter was cancelled.
|
||||
if (_waiter != null && _waiter.Task.IsCanceled)
|
||||
{
|
||||
_waiter = null;
|
||||
}
|
||||
}
|
||||
|
||||
void ThrowIfDisposed()
|
||||
{
|
||||
if (_isDisposed)
|
||||
|
||||
Reference in New Issue
Block a user