Fix OperationCancelledException and add IAsyncEnumerable to wait without thread blocking (#1562)

* Fixed Task Scheduler operation cancelled error caused by Orphaned RunCleanup task on RequestQueue not being awaited on dispose

* Added async disposable interface to various components

* Added incorrect early marking of disposed for DiscordSocketApi client

* Added general task canceled exception catch to cleanup task

* Fix merge errors

Co-authored-by: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Co-authored-by: quin lynch <lynchquin@gmail.com>
This commit is contained in:
James Grant
2022-01-11 17:24:30 +10:00
committed by GitHub
parent 4ed4718e18
commit cd36bb802b
8 changed files with 136 additions and 6 deletions

View File

@@ -568,6 +568,25 @@ namespace Discord.WebSocket
base.Dispose(disposing);
}
internal override ValueTask DisposeAsync(bool disposing)
{
if (!_isDisposed)
{
if (disposing)
{
if (_shards != null)
{
foreach (var client in _shards)
client?.Dispose();
}
}
_isDisposed = true;
}
return base.DisposeAsync(disposing);
}
#endregion
}
}

View File

@@ -124,12 +124,39 @@ namespace Discord.API
_decompressor?.Dispose();
_compressed?.Dispose();
}
_isDisposed = true;
}
base.Dispose(disposing);
}
#if NETSTANDARD2_1
internal override async ValueTask DisposeAsync(bool disposing)
#else
internal override ValueTask DisposeAsync(bool disposing)
#endif
{
if (!_isDisposed)
{
if (disposing)
{
_connectCancelToken?.Dispose();
(WebSocketClient as IDisposable)?.Dispose();
#if NETSTANDARD2_1
if (!(_decompressor is null))
await _decompressor.DisposeAsync().ConfigureAwait(false);
#else
_decompressor?.Dispose();
#endif
}
}
#if NETSTANDARD2_1
await base.DisposeAsync(disposing).ConfigureAwait(false);
#else
return base.DisposeAsync(disposing);
#endif
}
public async Task ConnectAsync()
{
await _stateLock.WaitAsync().ConfigureAwait(false);

View File

@@ -213,6 +213,27 @@ namespace Discord.WebSocket
base.Dispose(disposing);
}
internal override async ValueTask DisposeAsync(bool disposing)
{
if (!_isDisposed)
{
if (disposing)
{
await StopAsync().ConfigureAwait(false);
if (!(ApiClient is null))
await ApiClient.DisposeAsync().ConfigureAwait(false);
_stateLock?.Dispose();
}
_isDisposed = true;
}
await base.DisposeAsync(disposing).ConfigureAwait(false);
}
/// <inheritdoc />
internal override async Task OnLoginAsync(TokenType tokenType, string token)
{
if (_shardedClient == null && _defaultStickers.Length == 0 && AlwaysDownloadDefaultStickers)