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;
5:
6: // set the event handler to complete the task
7: routedEventHandler = (Object s, RoutedEventArgs e) => tsc.SetResult(e);
8:
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
- Anonymous
August 06, 2013
So you can unhook the event. - Anonymous
August 11, 2013
is it because you need the finally code to happen after the task has completed? - Anonymous
August 12, 2013
The comment has been removed