Wednesday, May 2, 2012

Async II: Exception Handling

In the previous blog post, we looked at the basics of async. In this post, we will look at exception handling. You need exception handling the moment something goes wrong in an asynchronous call. When this happens, the Task that comes out of the asynchronous call will have an error status and you won't be able to get the result from the method.

Handling these kinds of error situations is actually really simple. The only thing you need to do is wrap your asynchronous call in a try - catch statement, just like you would do with synchronous code. Let's take a look at an example:

public async Task PublishHikeRequest()
{
    var hikeRequest = GetHikeRequest();

    try
    {
        var client = new HttpClient();

        var url = string.Format("{0}/HikeRequest", BASE_URL);
        var response = await client.PostAsync(url, await BuildJsonContent(hikeRequest));
        response.EnsureSuccessStatusCode();
    }
    catch (Exception exc)
    {
        var dialog = new MessageDialog(exc.Message);
        dialog.ShowAsync();
    }
}

This method can be found in the RestCaller class, the one that's being used in the OnNavigatedTo from the previous blog post. In this method we post a message to a REST service in an asynchronous way. There are a couple of points where this code can give us error situations. The REST service can be down or for some reason our Json message can't be build as expected. For this we use a try catch clause to wrap the asynchronous calls.

Simpler than this, they can't make it for you. I just want to point out one more thing. Don't do as I did and show a MessageDialog in your catch clause. I just put it there for demoing purposes, but it can really bite you in the butt. Let me explain: If the REST service is down, it will take a while for the timeout of the call, giving a HttpRequestException, to kick in (this is about one minute). By this time, it is very well possible that the user of your application has already performed 10 other actions. The MessageDialog will only get him confused, because it's a reaction to an action he performed a minute ago. For this it is important that you know how to cancel actions that were kicked off, but are no longer relevant in the current user context.

That is why, in the next blog post, we will look at cancellation (and progress reporting).

And just another small thought on asynchronous calls I want to add. After the Visug session I got a question asking if you don't need to keep track of your background threads and if in the PublishHikeRequest method I can do stuff with my UI (for instance alter text in a TextBox). The answer is: yes you can. Your code actually executes synchronously until you get an await. This means all code in PublishHikeRequest is synchronous up until the PostAsync call. This is a framework call that actually does some stuff with threadpools or async I/O. But we don't need to worry about that. All of our code is still synchronous. And the callback that is being build for us, with the rest of our message body, will again be called on the UI thread. So, to sum up, nothing to worry about, go ahead and alter the text of that TextBox.

No comments:

Post a Comment