Skip to content

Instantly share code, notes, and snippets.

@neuecc
Last active August 7, 2022 13:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save neuecc/e190a01aeddf6be6e15b837216c0be2e to your computer and use it in GitHub Desktop.
Save neuecc/e190a01aeddf6be6e15b837216c0be2e to your computer and use it in GitHub Desktop.
class Client : IDisposable
{
// called from IDisposable.Dispose
readonly CancellationTokenSource clientLifetimeTokenSource;
public TimeSpan Timeout { get; }
public Client(TimeSpan timeout)
{
this.Timeout = timeout;
this.clientLifetimeTokenSource = new CancellationTokenSource();
}
public async Task SendAsync(CancellationToken cancellationToken = default)
{
using var cts = CancellationTokenSource.CreateLinkedTokenSource(clientLifetimeTokenSource.Token, cancellationToken);
cts.CancelAfter(Timeout);
try
{
await SendCoreAsync(cts.Token);
}
catch (OperationCanceledException ex) when (ex.CancellationToken == cts.Token)
{
if (cancellationToken.IsCancellationRequested)
{
// Error reason is argument CancellationToken
throw new OperationCanceledException(ex.Message, ex, cancellationToken);
}
else if (clientLifetimeTokenSource.IsCancellationRequested)
{
// Error reason is client's dispose
throw new OperationCanceledException("Client is disposed.", ex, clientLifetimeTokenSource.Token);
}
else
{
// Error reason is timeout
throw new TimeoutException($"The request was canceled due to the configured Timeout of {Timeout.TotalSeconds} seconds elapsing.", ex);
}
}
}
async Task SendCoreAsync(CancellationToken cancellationToken)
{
// nanika...
}
public void Dispose()
{
clientLifetimeTokenSource.Cancel();
clientLifetimeTokenSource.Dispose();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment