Exception Handling With Tasks.WhenAll()

,

In a recent project IntelliTect developed for a client, we were working with an architecture that involved a client application communicating with an Azure app service, which communicated with a private on-premise web API service.  When attempting to transfer a very large file via a HttpResponse, we were hitting a failure that prevented the file from being downloaded.  Even though we have significant logging in place through our entire pipeline (client, middle tier, and on-premise server), we weren’t able to quickly identify the cause of the failure.  After further investigation of the Azure application events, we were able to see that some of our middle tier code in the Azure app service was failing.  The application event indicated that we hit a TaskCanceledException in one of our Azure app service apis.  This was very interesting, however, because we have extensive logging in our Azure app service that catches any exceptions thrown, and logs the exception information.  Our log file in this case, though, did not have any exceptions logged.

This got us to dig deeper, and we were able to quickly identify the reason for our missing log data.  In the client’s code, there was a method that had code similar to this:

As you can see from the code above, any exception in the catch handler should have been caught by the catch clause.  The code was not catching the exception, however, because the code was not written to use Task.WhenAll properly.  Task.WhenAll will not throw all exceptions when it encounters them.  Instead, it adds them to an AggregateException, that must be checked at the end of waiting for the tasks to complete. Note that the above code will throw the first exception that is encountered, but if there is more than 1, it will not catch all of them.  To correct the code, we wrote the following helper method:

This new code will now re-throw an AggregateException if one exists after waiting for the tasks to complete.  After adding this code, we were able to successfully track down which task in the client’s code was getting canceled, by viewing our logs.

For a full example, please download the following solution: http://intellitect.com/wp-content/uploads/2017/07/WhenAllTest.zip

2 responses to “Exception Handling With Tasks.WhenAll()

  1. This post is very misleading and has in fact caused us a great deal of time wasted.
    awaiting Task.WhenAll *does in fact throw an exception* – the first its inner tasks’ exceptions.

    just build a demo project and see for yourself.

    1. Hi Yoav,

      Sorry you had difficulty with this. You are correct, that it does throw the first exception, I wasn’t quite clear on that. If there are multiple exceptions, it will not catch all of them, however. I’ve updated the blog post to indicate this, and uploaded a complete sample project that you can play around with if you want to.

      -Jason

Leave a Reply

Your email address will not be published. Required fields are marked *