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

@@ -25,8 +25,9 @@ namespace Discord.WebSocket
/// Represents a WebSocket-based guild object.
/// </summary>
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class SocketGuild : SocketEntity<ulong>, IGuild
public class SocketGuild : SocketEntity<ulong>, IGuild, IDisposable
{
#pragma warning disable IDISP002, IDISP006
private readonly SemaphoreSlim _audioLock;
private TaskCompletionSource<bool> _syncPromise, _downloaderPromise;
private TaskCompletionSource<AudioClient> _audioConnectPromise;
@@ -37,6 +38,7 @@ namespace Discord.WebSocket
private ImmutableArray<GuildEmote> _emotes;
private ImmutableArray<string> _features;
private AudioClient _audioClient;
#pragma warning restore IDISP002, IDISP006
/// <inheritdoc />
public string Name { get; private set; }
@@ -63,7 +65,7 @@ namespace Discord.WebSocket
/// number here is the most accurate in terms of counting the number of users within this guild.
/// </para>
/// <para>
/// Use this instead of enumerating the count of the
/// Use this instead of enumerating the count of the
/// <see cref="Discord.WebSocket.SocketGuild.Users" /> collection, as you may see discrepancy
/// between that and this property.
/// </para>
@@ -872,9 +874,11 @@ namespace Discord.WebSocket
if (external)
{
#pragma warning disable IDISP001
var _ = promise.TrySetResultAsync(null);
await Discord.ApiClient.SendVoiceStateUpdateAsync(Id, channelId, selfDeaf, selfMute).ConfigureAwait(false);
return null;
#pragma warning restore IDISP001
}
if (_audioClient == null)
@@ -897,10 +901,14 @@ namespace Discord.WebSocket
};
audioClient.Connected += () =>
{
#pragma warning disable IDISP001
var _ = promise.TrySetResultAsync(_audioClient);
#pragma warning restore IDISP001
return Task.Delay(0);
};
#pragma warning disable IDISP003
_audioClient = audioClient;
#pragma warning restore IDISP003
}
await Discord.ApiClient.SendVoiceStateUpdateAsync(Id, channelId, selfDeaf, selfMute).ConfigureAwait(false);
@@ -948,6 +956,7 @@ namespace Discord.WebSocket
if (_audioClient != null)
await _audioClient.StopAsync().ConfigureAwait(false);
await Discord.ApiClient.SendVoiceStateUpdateAsync(Id, null, false, false).ConfigureAwait(false);
_audioClient?.Dispose();
_audioClient = null;
}
internal async Task FinishConnectAudio(string url, string token)
@@ -1130,5 +1139,12 @@ namespace Discord.WebSocket
/// <inheritdoc />
async Task<IReadOnlyCollection<IWebhook>> IGuild.GetWebhooksAsync(RequestOptions options)
=> await GetWebhooksAsync(options).ConfigureAwait(false);
void IDisposable.Dispose()
{
DisconnectAudioAsync().GetAwaiter().GetResult();
_audioLock?.Dispose();
_audioClient?.Dispose();
}
}
}