Skip to content

Instantly share code, notes, and snippets.

@Emzi0767
Last active March 28, 2019 18:38
Show Gist options
  • Save Emzi0767/e46451b6980eccea1db53ec393afec35 to your computer and use it in GitHub Desktop.
Save Emzi0767/e46451b6980eccea1db53ec393afec35 to your computer and use it in GitHub Desktop.
// Copyright 2019 Emzi0767
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* Documentation of all the relevant types:
*
* System.Threading.Tasks.Task
* https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task?view=netcore-2.2
*
* System.Threading.Tasks.TaskContinuationOptions
* https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskcontinuationoptions?view=netcore-2.2
*
* System.Threading.SemaphoreSlim
* https://docs.microsoft.com/en-us/dotnet/api/system.threading.semaphoreslim?view=netcore-2.2
*
* System.Threading.CancellationToken
* https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken?view=netcore-2.2
*
* System.Threading.CancellationTokenSource
* https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource?view=netcore-2.2
*
* DSharpPlus.DiscordClient
* https://dsharpplus.github.io/api/DSharpPlus.DiscordClient.html
*/
/* THE FOLLOWING ASSUMES EXISTENCE OF FOLLOWING PROPERTIES */
SemaphoreSlim LockerInstance { get; set; }
CancellationTokenSource TokenSource { get; set; }
CancellationToken Token => TokenSource.Token;
/* OBTAINING THE LOCKER INSTANCE */
using System.Reflection;
using System.Threading;
var t = typeof(DiscordClient);
var prop = t.GetProperty("ConnectionSemaphore", BindingFlags.NonPublic | BindingFlags.Static);
LockerInstance = prop.GetValue(null) as SemaphoreSlim;
/* DISCORD SOCKET EVENT HANDLERS */
Task DiscordSocketClosed(SocketCloseEventArgs e) // handles DiscordClient#SocketClosed
{
try
{
// dispose of the token source - it will leak otherwise
TokenSource?.Cancel();
TokenSource?.Dispose();
}
catch { /* swallow exceptions since they're not relevant */ }
TokenSource = new CancellationTokenSource();
UnlockTask = Task.Delay(TimeSpan.FromSeconds(15 /* This can technically be anything so long as it's >=5 */), Token);
UnlockTask.ContinueWith(UnlockerContinuation, TokenSource, TaskContinuationOptions.OnlyOnRanToCompletion);
return Task.CompletedTask;
void UnlockerContinuation(Task t, object state)
{
if (!(state is CancellationTokenSource cts))
return;
try
{
// they are not null, otherwise it would not match
cts.Cancel();
cts.Dispose();
}
catch { /* swallow exceptions since they're not relevant */ }
}
}
Task DiscordSocketOpened() // handles DiscordClient#SocketOpened
{
try
{
// canel the token and dispose it - we don't need to unlock since connection attempt seems to have been successful
TokenSource.Cancel();
TokenSource.Dispose();
}
catch { /* swallow exceptions since they're not relevant */ }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment