Cancellable “awaiting” on .NET events continued

Compose, compose, compose. Reuse, reuse, reuse.

In the last post on cancellable “awaiting” on .NET events, I was so busy focusing on the wrapping the click event in order to get a smooth async control flow for the caller, I neglected to do the same inside the click event wrapper code.

The framework team already provided an extension method (WithCancellation) to make any task cancellable. By using WithCancellation(), we can do away with the Continuation call and just use a simple try/finally block to guarantee that the event handler gets unsubscribed regardless of how the task finishes.


   1: public static async Task<RoutedEventArgs> WhenClicked(this Button element, CancellationToken token)
   2: {
   3:     TaskCompletionSource<RoutedEventArgs> tsc = new TaskCompletionSource<RoutedEventArgs>();
   4:     RoutedEventHandler routedEventHandler = null;
   6:     // set the event handler to complete the task
   7:     routedEventHandler = (Object s, RoutedEventArgs e) => tsc.SetResult(e);
   9:     // hook up to the event
  10:     element.Click += routedEventHandler;
  11:     try
  12:     { 
  13:         return await tsc.Task.WithCancellation(token);
  14:     }
  15:     finally
  16:     {
  17:         // always unhook the event handler after the task is finished
  18:         element.Click -= routedEventHandler;
  19:     }
  20: }

FOR BONUS POINTS: Why do we have to make this method async? Why not just return a task instead and not use await on line 13.

Comments (3)

  1. lbargaoanu says:

    So you can unhook the event.

  2. Ross Dargan says:

    is it because you need the finally code to happen after the task has completed?

  3. BenWilli says:

    Yes, the event will get unhooked either way. The finally block guarantees that. But if you were to just return the task, then the finally block would execute immediately and unhook the event. Then the task would never complete. With the async/await in place, the code below it (the finally block) wont execute until the task is complete.

Skip to main content