feature: Implement Dispose for types which have disposable data (#1171)

* Initial set of dispose implementations

Not handled yet:
- Discord.Net.Websocket/Entities/SocketGuild
- Discord.Net.Tests

* Refactor DiscordSocketClient init into ctor

This way we remove an IDisposableAnalyzer warning for not disposing
the client when we set the client variable.

* Dispose of clients when disposing sharded client

* Finish implementing IDisposable where appropriate

I opted to use NoWarn in the Tests project as it wasn't really necessary
considering that our tests only run once

* Tweak samples after feedback
This commit is contained in:
Monica S
2018-11-29 01:18:16 +00:00
committed by Christopher F
parent dca6c33da3
commit 7366cd4361
31 changed files with 406 additions and 154 deletions

View File

@@ -16,23 +16,24 @@ namespace Discord.Net.Queue
private readonly ConcurrentDictionary<string, RequestBucket> _buckets;
private readonly SemaphoreSlim _tokenLock;
private readonly CancellationTokenSource _cancelToken; //Dispose token
private readonly CancellationTokenSource _cancelTokenSource; //Dispose token
private CancellationTokenSource _clearToken;
private CancellationToken _parentToken;
private CancellationTokenSource _requestCancelTokenSource;
private CancellationToken _requestCancelToken; //Parent token + Clear token
private DateTimeOffset _waitUntil;
private Task _cleanupTask;
public RequestQueue()
{
_tokenLock = new SemaphoreSlim(1, 1);
_clearToken = new CancellationTokenSource();
_cancelToken = new CancellationTokenSource();
_cancelTokenSource = new CancellationTokenSource();
_requestCancelToken = CancellationToken.None;
_parentToken = CancellationToken.None;
_buckets = new ConcurrentDictionary<string, RequestBucket>();
_cleanupTask = RunCleanup();
@@ -44,7 +45,9 @@ namespace Discord.Net.Queue
try
{
_parentToken = cancelToken;
_requestCancelToken = CancellationTokenSource.CreateLinkedTokenSource(cancelToken, _clearToken.Token).Token;
_requestCancelTokenSource?.Dispose();
_requestCancelTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancelToken, _clearToken.Token);
_requestCancelToken = _requestCancelTokenSource.Token;
}
finally { _tokenLock.Release(); }
}
@@ -54,9 +57,14 @@ namespace Discord.Net.Queue
try
{
_clearToken?.Cancel();
_clearToken?.Dispose();
_clearToken = new CancellationTokenSource();
if (_parentToken != null)
_requestCancelToken = CancellationTokenSource.CreateLinkedTokenSource(_clearToken.Token, _parentToken).Token;
{
_requestCancelTokenSource?.Dispose();
_requestCancelTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_clearToken.Token, _parentToken);
_requestCancelToken = _requestCancelTokenSource.Token;
}
else
_requestCancelToken = _clearToken.Token;
}
@@ -65,13 +73,19 @@ namespace Discord.Net.Queue
public async Task<Stream> SendAsync(RestRequest request)
{
CancellationTokenSource createdTokenSource = null;
if (request.Options.CancelToken.CanBeCanceled)
request.Options.CancelToken = CancellationTokenSource.CreateLinkedTokenSource(_requestCancelToken, request.Options.CancelToken).Token;
{
createdTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_requestCancelToken, request.Options.CancelToken);
request.Options.CancelToken = createdTokenSource.Token;
}
else
request.Options.CancelToken = _requestCancelToken;
var bucket = GetOrCreateBucket(request.Options.BucketId, request);
return await bucket.SendAsync(request).ConfigureAwait(false);
var result = await bucket.SendAsync(request).ConfigureAwait(false);
createdTokenSource?.Dispose();
return result;
}
public async Task SendAsync(WebSocketRequest request)
{
@@ -109,7 +123,7 @@ namespace Discord.Net.Queue
{
try
{
while (!_cancelToken.IsCancellationRequested)
while (!_cancelTokenSource.IsCancellationRequested)
{
var now = DateTimeOffset.UtcNow;
foreach (var bucket in _buckets.Select(x => x.Value))
@@ -117,7 +131,7 @@ namespace Discord.Net.Queue
if ((now - bucket.LastAttemptAt).TotalMinutes > 1.0)
_buckets.TryRemove(bucket.Id, out _);
}
await Task.Delay(60000, _cancelToken.Token).ConfigureAwait(false); //Runs each minute
await Task.Delay(60000, _cancelTokenSource.Token).ConfigureAwait(false); //Runs each minute
}
}
catch (OperationCanceledException) { }
@@ -126,7 +140,10 @@ namespace Discord.Net.Queue
public void Dispose()
{
_cancelToken.Dispose();
_cancelTokenSource?.Dispose();
_tokenLock?.Dispose();
_clearToken?.Dispose();
_requestCancelTokenSource?.Dispose();
}
}
}