All cancelTokens should be linked to the parent's. Always cache cancelTokens.
This commit is contained in:
@@ -75,8 +75,9 @@ namespace Discord
|
||||
public Users Users => _users;
|
||||
private readonly Users _users;
|
||||
|
||||
public CancellationToken CancelToken => _cancelToken.Token;
|
||||
private CancellationTokenSource _cancelToken;
|
||||
public CancellationToken CancelToken => _cancelToken;
|
||||
private CancellationTokenSource _cancelTokenSource;
|
||||
private CancellationToken _cancelToken;
|
||||
|
||||
/// <summary> Initializes a new instance of the DiscordClient class. </summary>
|
||||
public DiscordClient(DiscordClientConfig config = null)
|
||||
@@ -509,7 +510,7 @@ namespace Discord
|
||||
if (_config.EnableVoice)
|
||||
{
|
||||
string host = "wss://" + data.Endpoint.Split(':')[0];
|
||||
await _voiceSocket.Login(host, data.GuildId, _currentUserId, _dataSocket.SessionId, data.Token).ConfigureAwait(false);
|
||||
await _voiceSocket.Login(host, data.GuildId, _currentUserId, _dataSocket.SessionId, data.Token, _cancelToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -576,7 +577,8 @@ namespace Discord
|
||||
try
|
||||
{
|
||||
_disconnectedEvent.Reset();
|
||||
_cancelToken = new CancellationTokenSource();
|
||||
_cancelTokenSource = new CancellationTokenSource();
|
||||
_cancelToken = _cancelTokenSource.Token;
|
||||
_state = (int)DiscordClientState.Connecting;
|
||||
|
||||
_api.Token = token;
|
||||
@@ -584,14 +586,14 @@ namespace Discord
|
||||
if (_config.LogLevel >= LogMessageSeverity.Verbose)
|
||||
RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Authentication, $"Websocket endpoint: {url}");
|
||||
|
||||
await _dataSocket.Login(url, token).ConfigureAwait(false);
|
||||
await _dataSocket.Login(url, token, _cancelToken).ConfigureAwait(false);
|
||||
|
||||
_runTask = RunTasks();
|
||||
|
||||
try
|
||||
{
|
||||
//Cancel if either Disconnect is called, data socket errors or timeout is reached
|
||||
var cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_cancelToken.Token, _dataSocket.CancelToken).Token;
|
||||
var cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_cancelToken, _dataSocket.CancelToken).Token;
|
||||
if (!_connectedEvent.Wait(_config.ConnectionTimeout, cancelToken))
|
||||
throw new Exception("Operation timed out.");
|
||||
}
|
||||
@@ -638,7 +640,7 @@ namespace Discord
|
||||
{
|
||||
_wasDisconnectUnexpected = isUnexpected;
|
||||
_disconnectReason = ExceptionDispatchInfo.Capture(ex);
|
||||
_cancelToken.Cancel();
|
||||
_cancelTokenSource.Cancel();
|
||||
}
|
||||
|
||||
if (!skipAwait)
|
||||
@@ -730,7 +732,7 @@ namespace Discord
|
||||
//Experimental
|
||||
private Task MessageQueueLoop()
|
||||
{
|
||||
var cancelToken = _cancelToken.Token;
|
||||
var cancelToken = _cancelToken;
|
||||
int interval = _config.MessageQueueInterval;
|
||||
|
||||
return Task.Run(async () =>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Net.WebSockets
|
||||
@@ -18,9 +19,9 @@ namespace Discord.Net.WebSockets
|
||||
{
|
||||
}
|
||||
|
||||
public async Task Login(string host, string token)
|
||||
public async Task Login(string host, string token, CancellationToken cancelToken)
|
||||
{
|
||||
await base.Connect(host);
|
||||
await base.Connect(host, cancelToken);
|
||||
|
||||
Commands.Login msg = new Commands.Login();
|
||||
msg.Payload.Token = token;
|
||||
|
||||
@@ -52,14 +52,14 @@ namespace Discord.Net.WebSockets
|
||||
_targetAudioBufferLength = client.Config.VoiceBufferLength / 20; //20 ms frames
|
||||
}
|
||||
|
||||
public Task Login(string host, string serverId, string userId, string sessionId, string token)
|
||||
public Task Login(string host, string serverId, string userId, string sessionId, string token, CancellationToken cancelToken)
|
||||
{
|
||||
_serverId = serverId;
|
||||
_userId = userId;
|
||||
_sessionId = sessionId;
|
||||
_token = token;
|
||||
|
||||
return base.Connect(host);
|
||||
return base.Connect(host, cancelToken);
|
||||
}
|
||||
|
||||
protected override Task[] Run()
|
||||
@@ -110,8 +110,7 @@ namespace Discord.Net.WebSockets
|
||||
|
||||
private async Task ReceiveVoiceAsync()
|
||||
{
|
||||
var cancelSource = _cancelToken;
|
||||
var cancelToken = cancelSource.Token;
|
||||
var cancelToken = _cancelToken;
|
||||
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
@@ -145,8 +144,8 @@ namespace Discord.Net.WebSockets
|
||||
#else
|
||||
private Task SendVoiceAsync()
|
||||
{
|
||||
var cancelSource = _cancelToken;
|
||||
var cancelToken = cancelSource.Token;
|
||||
var cancelToken = _cancelToken;
|
||||
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
#endif
|
||||
@@ -239,7 +238,7 @@ namespace Discord.Net.WebSockets
|
||||
//Closes the UDP socket when _disconnectToken is triggered, since UDPClient doesn't allow passing a canceltoken
|
||||
private Task WatcherAsync()
|
||||
{
|
||||
var cancelToken = _cancelToken.Token;
|
||||
var cancelToken = _cancelToken;
|
||||
return cancelToken.Wait()
|
||||
.ContinueWith(_ => _udp.Close());
|
||||
}
|
||||
@@ -387,7 +386,7 @@ namespace Discord.Net.WebSockets
|
||||
|
||||
public void SendPCMFrames(byte[] data, int bytes)
|
||||
{
|
||||
var cancelToken = _cancelToken.Token;
|
||||
var cancelToken = _cancelToken;
|
||||
if (!_isReady || cancelToken == null)
|
||||
throw new InvalidOperationException("Not connected to a voice server.");
|
||||
if (bytes == 0)
|
||||
@@ -441,7 +440,7 @@ namespace Discord.Net.WebSockets
|
||||
Buffer.BlockCopy(_encodingBuffer, 0, payload, 0, encodedLength);
|
||||
|
||||
//Wait until the queue has a spot open
|
||||
_sendQueueWait.Wait(_cancelToken.Token);
|
||||
_sendQueueWait.Wait(_cancelToken);
|
||||
_sendQueue.Enqueue(payload);
|
||||
if (_sendQueue.Count >= _targetAudioBufferLength)
|
||||
_sendQueueWait.Reset();
|
||||
|
||||
@@ -47,8 +47,9 @@ namespace Discord.Net.WebSockets
|
||||
protected ExceptionDispatchInfo _disconnectReason;
|
||||
private bool _wasDisconnectUnexpected;
|
||||
|
||||
public CancellationToken CancelToken => _cancelToken.Token;
|
||||
protected CancellationTokenSource _cancelToken;
|
||||
public CancellationToken CancelToken => _cancelToken;
|
||||
private CancellationTokenSource _cancelTokenSource;
|
||||
protected CancellationToken _cancelToken;
|
||||
|
||||
public WebSocket(DiscordClient client)
|
||||
{
|
||||
@@ -64,20 +65,18 @@ namespace Discord.Net.WebSockets
|
||||
};
|
||||
}
|
||||
|
||||
protected virtual async Task Connect(string host)
|
||||
protected virtual async Task Connect(string host, CancellationToken cancelToken)
|
||||
{
|
||||
if (_state != (int)WebSocketState.Disconnected)
|
||||
throw new InvalidOperationException("Client is already connected or connecting to the server.");
|
||||
|
||||
try
|
||||
{
|
||||
await Disconnect().ConfigureAwait(false);
|
||||
|
||||
_state = (int)WebSocketState.Connecting;
|
||||
|
||||
_cancelToken = new CancellationTokenSource();
|
||||
_cancelTokenSource = new CancellationTokenSource();
|
||||
_cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_cancelTokenSource.Token, cancelToken).Token;
|
||||
|
||||
await _engine.Connect(host, _cancelToken.Token).ConfigureAwait(false);
|
||||
await _engine.Connect(host, _cancelToken).ConfigureAwait(false);
|
||||
_host = host;
|
||||
_lastHeartbeat = DateTime.UtcNow;
|
||||
|
||||
@@ -94,8 +93,8 @@ namespace Discord.Net.WebSockets
|
||||
_state = (int)WebSocketState.Connected;
|
||||
RaiseConnected();
|
||||
}
|
||||
public Task Reconnect()
|
||||
=> Connect(_host);
|
||||
/*public Task Reconnect(CancellationToken cancelToken)
|
||||
=> Connect(_host, _cancelToken);*/
|
||||
|
||||
public Task Disconnect() => DisconnectInternal(new Exception("Disconnect was requested by user."), isUnexpected: false);
|
||||
protected async Task DisconnectInternal(Exception ex, bool isUnexpected = true, bool skipAwait = false)
|
||||
@@ -118,7 +117,7 @@ namespace Discord.Net.WebSockets
|
||||
{
|
||||
_wasDisconnectUnexpected = isUnexpected;
|
||||
_disconnectReason = ExceptionDispatchInfo.Capture(ex);
|
||||
_cancelToken.Cancel();
|
||||
_cancelTokenSource.Cancel();
|
||||
}
|
||||
|
||||
if (!skipAwait)
|
||||
@@ -154,12 +153,16 @@ namespace Discord.Net.WebSockets
|
||||
}
|
||||
protected virtual Task[] Run()
|
||||
{
|
||||
var cancelToken = _cancelToken.Token;
|
||||
var cancelToken = _cancelToken;
|
||||
return _engine.RunTasks(cancelToken)
|
||||
.Concat(new Task[] { HeartbeatAsync(cancelToken) })
|
||||
.ToArray();
|
||||
}
|
||||
protected virtual Task Cleanup() { return TaskHelper.CompletedTask; }
|
||||
protected virtual Task Cleanup()
|
||||
{
|
||||
_cancelTokenSource = null;
|
||||
return TaskHelper.CompletedTask;
|
||||
}
|
||||
|
||||
protected abstract Task ProcessMessage(string json);
|
||||
protected abstract object GetKeepAlive();
|
||||
|
||||
Reference in New Issue
Block a user