Last time we saw how to wait for async void methods. Today we are going to catch exceptions. Normally exceptions thrown by those methods crash application because we cannot wait for them. Exceptions from async Task on the other hand don’t do that generally (they can when the GC cleans up and unobserved exception is being thrown) but silently wait for us to be handled. We would like to have exactly the same behavior, so let’s see, how we can do that.

Last time we implemented custom synchronization context. Today we need something more — task scheduler:

We have collection of tasks to execute. Whenever we queue new task, we just store it in the array instead of trying to execute it right away. Effectively those tasks are not run at all until we say so.

We create new TaskFactory with our scheduler so whatever we run on this factory will go through our logic. Next, we count operations so we know when we are done.

Finally, we have a helper method for running the tasks. We replace synchronization context with ours, submit a task with lambda provided by the caller, and then execute all tasks from the scheduler one by one. We wait for all the tasks so whatever exception is thrown we just “catch” it with ordinary Task mechanisms.