Share via


Task-based Asynchronous Pattern - WithCancellation

if you're working with a Task based API that does not follow the TAP rules and hence does not expose an option to cancel you can always add your own this way:

  1: public static Task<T> WithCancellation<T>(
 2:     this Task<T> task, 
 3:     CancellationToken cancellationToken)
 4: {
 5:     var taskCompletionSource = new TaskCompletionSource<T>();
 6:     var cancellationRegistration = cancellationToken.Register(
 7:         () => taskCompletionSource.TrySetCanceled());
 8:     task.ContinueWith(
 9:         t =>
 10:             {
 11:                 cancellationRegistration.Dispose();
 12:                 if (t.IsCanceled)
 13:                 {
 14:                     taskCompletionSource.TrySetCanceled();
 15:                 }
 16:                 else if (t.IsFaulted)
 17:                 {
 18:                     taskCompletionSource.TrySetException(
 19:                         t.Exception.InnerException);
 20:                 }
 21:                 else
 22:                 {
 23:                     taskCompletionSource.TrySetResult(t.Result);
 24:                 }
 25:             });
 26:     return taskCompletionSource.Task;
 27: }

This naturally will not actually stop the task you wrap this way but at least it returns control to the code waiting for completion faster.