| @@ -8,7 +8,7 @@ namespace Discord | |||
| /// <summary> | |||
| /// Represents a generic Discord client. | |||
| /// </summary> | |||
| public interface IDiscordClient : IDisposable | |||
| public interface IDiscordClient : IDisposable, IAsyncDisposable | |||
| { | |||
| /// <summary> | |||
| /// Gets the current state of connection. | |||
| @@ -145,9 +145,24 @@ namespace Discord.Rest | |||
| _isDisposed = true; | |||
| } | |||
| } | |||
| internal virtual async ValueTask DisposeAsync(bool disposing) | |||
| { | |||
| if (!_isDisposed) | |||
| { | |||
| #pragma warning disable IDISP007 | |||
| await ApiClient.DisposeAsync().ConfigureAwait(false); | |||
| #pragma warning restore IDISP007 | |||
| _stateLock?.Dispose(); | |||
| _isDisposed = true; | |||
| } | |||
| } | |||
| /// <inheritdoc /> | |||
| public void Dispose() => Dispose(true); | |||
| public ValueTask DisposeAsync() => DisposeAsync(true); | |||
| /// <inheritdoc /> | |||
| public Task<int> GetRecommendedShardCountAsync(RequestOptions options = null) | |||
| => ClientHelper.GetRecommendShardCountAsync(this, options); | |||
| @@ -22,7 +22,7 @@ using System.Threading.Tasks; | |||
| namespace Discord.API | |||
| { | |||
| internal class DiscordRestApiClient : IDisposable | |||
| internal class DiscordRestApiClient : IDisposable, IAsyncDisposable | |||
| { | |||
| private static readonly ConcurrentDictionary<string, Func<BucketIds, string>> _bucketIdGenerators = new ConcurrentDictionary<string, Func<BucketIds, string>>(); | |||
| @@ -106,8 +106,29 @@ namespace Discord.API | |||
| _isDisposed = true; | |||
| } | |||
| } | |||
| internal virtual async ValueTask DisposeAsync(bool disposing) | |||
| { | |||
| if (!_isDisposed) | |||
| { | |||
| if (disposing) | |||
| { | |||
| _loginCancelToken?.Dispose(); | |||
| RestClient?.Dispose(); | |||
| if (!(RequestQueue is null)) | |||
| await RequestQueue.DisposeAsync().ConfigureAwait(false); | |||
| _stateLock?.Dispose(); | |||
| } | |||
| _isDisposed = true; | |||
| } | |||
| } | |||
| public void Dispose() => Dispose(true); | |||
| public ValueTask DisposeAsync() => DisposeAsync(true); | |||
| public async Task LoginAsync(TokenType tokenType, string token, RequestOptions options = null) | |||
| { | |||
| await _stateLock.WaitAsync().ConfigureAwait(false); | |||
| @@ -41,6 +41,14 @@ namespace Discord.Rest | |||
| base.Dispose(disposing); | |||
| } | |||
| internal override async ValueTask DisposeAsync(bool disposing) | |||
| { | |||
| if (disposing) | |||
| await ApiClient.DisposeAsync().ConfigureAwait(false); | |||
| base.Dispose(disposing); | |||
| } | |||
| /// <inheritdoc /> | |||
| internal override async Task OnLoginAsync(TokenType tokenType, string token) | |||
| { | |||
| @@ -1,3 +1,4 @@ | |||
| using Newtonsoft.Json.Bson; | |||
| using System; | |||
| using System.Collections.Concurrent; | |||
| #if DEBUG_LIMITS | |||
| @@ -10,7 +11,7 @@ using System.Threading.Tasks; | |||
| namespace Discord.Net.Queue | |||
| { | |||
| internal class RequestQueue : IDisposable | |||
| internal class RequestQueue : IDisposable, IAsyncDisposable | |||
| { | |||
| public event Func<string, RateLimitInfo?, Task> RateLimitTriggered; | |||
| @@ -143,12 +144,25 @@ namespace Discord.Net.Queue | |||
| if (!(_cancelTokenSource is null)) | |||
| { | |||
| _cancelTokenSource.Cancel(); | |||
| _cancelTokenSource?.Dispose(); | |||
| _cancelTokenSource.Dispose(); | |||
| _cleanupTask.GetAwaiter().GetResult(); | |||
| } | |||
| _tokenLock?.Dispose(); | |||
| _clearToken?.Dispose(); | |||
| _requestCancelTokenSource?.Dispose(); | |||
| } | |||
| public async ValueTask DisposeAsync() | |||
| { | |||
| if (!(_cancelTokenSource is null)) | |||
| { | |||
| _cancelTokenSource.Cancel(); | |||
| _cancelTokenSource.Dispose(); | |||
| await _cleanupTask.ConfigureAwait(false); | |||
| } | |||
| _tokenLock?.Dispose(); | |||
| _clearToken?.Dispose(); | |||
| _requestCancelTokenSource?.Dispose(); | |||
| } | |||
| } | |||
| } | |||
| @@ -402,5 +402,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(); | |||
| } | |||
| _connectionGroupLock?.Dispose(); | |||
| } | |||
| _isDisposed = true; | |||
| } | |||
| return base.DisposeAsync(disposing); | |||
| } | |||
| } | |||
| } | |||
| @@ -114,6 +114,35 @@ namespace Discord.API | |||
| 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 | |||
| } | |||
| _isDisposed = true; | |||
| } | |||
| #if NETSTANDARD2_1 | |||
| await base.DisposeAsync(disposing).ConfigureAwait(false); | |||
| #else | |||
| return base.DisposeAsync(disposing); | |||
| #endif | |||
| } | |||
| public async Task ConnectAsync() | |||
| { | |||
| await _stateLock.WaitAsync().ConfigureAwait(false); | |||
| @@ -197,6 +197,25 @@ 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) | |||
| { | |||