Fix memory leak in AsyncAutoResetEvent.

This commit is contained in:
Christian
2019-03-09 19:20:34 +01:00
committed by Christian Kratky
parent 4fed80c2d0
commit 5090cfb411
2 changed files with 48 additions and 1 deletions
+23 -1
View File
@@ -9,6 +9,7 @@ namespace MQTTnet.Internal
public class AsyncAutoResetEvent
{
private readonly LinkedList<TaskCompletionSource<bool>> _waiters = new LinkedList<TaskCompletionSource<bool>>();
private bool _isSignaled;
public AsyncAutoResetEvent()
@@ -21,6 +22,17 @@ namespace MQTTnet.Internal
_isSignaled = signaled;
}
public int WaitersCount
{
get
{
lock (_waiters)
{
return _waiters.Count;
}
}
}
public Task<bool> WaitOneAsync()
{
return WaitOneAsync(CancellationToken.None);
@@ -59,7 +71,17 @@ namespace MQTTnet.Internal
_waiters.AddLast(tcs);
}
var winner = await Task.WhenAny(tcs.Task, Task.Delay(timeout, cancellationToken)).ConfigureAwait(false);
Task winner;
if (timeout == Timeout.InfiniteTimeSpan)
{
await tcs.Task.ConfigureAwait(false);
winner = tcs.Task;
}
else
{
winner = await Task.WhenAny(tcs.Task, Task.Delay(timeout, cancellationToken)).ConfigureAwait(false);
}
var taskWasSignaled = winner == tcs.Task;
if (taskWasSignaled)
{
@@ -17,6 +17,31 @@ namespace MQTTnet.Core.Tests
_aare = new AsyncAutoResetEvent();
}
[TestMethod]
public async Task Cleanup_Waiters()
{
var @lock = new AsyncAutoResetEvent();
var waitOnePassed = false;
Task.Run(async () =>
{
await @lock.WaitOneAsync(TimeSpan.FromSeconds(2));
waitOnePassed = true;
});
await Task.Delay(500);
Assert.AreEqual(1, @lock.WaitersCount);
@lock.Set();
await Task.Delay(1000);
Assert.IsTrue(waitOnePassed);
Assert.AreEqual(0, @lock.WaitersCount);
}
[TestMethod]
public async Task SingleThreadedPulse()
{