Skip to content

Instantly share code, notes, and snippets.

@neuecc
Created August 3, 2022 08:42
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save neuecc/faa3dabc9dba234d7efae4e43a7da354 to your computer and use it in GitHub Desktop.
Save neuecc/faa3dabc9dba234d7efae4e43a7da354 to your computer and use it in GitHub Desktop.
public async Task SendAsync(CancellationToken cancellationToken = default)
{
var timeoutTokenSource = timeoutTokenSourcePool.Get();
CancellationTokenRegistration externalCancellation = default;
if (cancellationToken.CanBeCanceled)
{
externalCancellation = cancellationToken.UnsafeRegister(static state =>
{
((CancellationTokenSource)state!).Cancel();
}, timeoutTokenSource);
}
var clientLifetimeCancellation = clientLifetimeTokenSource.Token.UnsafeRegister(static state =>
{
((CancellationTokenSource)state!).Cancel();
}, timeoutTokenSource);
timeoutTokenSource.CancelAfter(Timeout);
try
{
await SendCoreAsync(timeoutTokenSource.Token);
}
catch (OperationCanceledException ex) when (ex.CancellationToken == timeoutTokenSource.Token)
{
// exception handling
if (cancellationToken.IsCancellationRequested)
{
throw new OperationCanceledException(ex.Message, ex, cancellationToken);
}
else if (clientLifetimeTokenSource.IsCancellationRequested)
{
throw new OperationCanceledException("Client is disposed.", ex, clientLifetimeTokenSource.Token);
}
else
{
throw new TimeoutException($"The request was canceled due to the configured Timeout of {Timeout.TotalSeconds} seconds elapsing.", ex);
}
}
finally
{
externalCancellation.Dispose();
clientLifetimeCancellation.Dispose();
if (timeoutTokenSource.TryReset())
{
timeoutTokenSourcePool.Return(timeoutTokenSource);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment