From the course: C#: Advanced Practices

Handling asynchronous exceptions - C# Tutorial

From the course: C#: Advanced Practices

Handling asynchronous exceptions

- In our last video we spoke about converting synchronous code to asynchronous code. In this video, we're going to talk about handling asynchronous errors. So Bill, I heard that I shouldn't use async void methods or that async void methods are like fire and forget and it's okay. But, is it okay? - It really isn't, you know unless you're one of those programmers and your code always works. Because sometimes tasks fail. And if you don't await a task, if you start an async void method, there's no way to decide what to do if a task fails. You know, I loved our description we did that you talked about last time, where that task is an object that shows you know, here's the results and here's the status. Well, that's also how you find out if a task fails and you see what happens. - [Mika] Great, let's look at some code. - [Bill] Okay, so this is WPF application, which is a very common scenario for async void methods. And when I run it, this will never win any design awards, but it's a basic little application that when you press do work, it's going to animate that ellipse, you know, squish it from both sides and then bring it back to a circle. It behaves well, but now if I start clicking it multiple times, and it starts that animation multiple times, some kind of strange things happen and it does some weird stuff. And then it recovers. So that's the application right now. - [Mika] Nice, it looks like you have some warnings over there. - [Bill] Yes I do. So that's that async void method. And if you look, the warning is telling me that I've started this asynchronous task, but I'm not awaiting it. So I'll do that. - [Mika] Right, and if your code never awaits that task, it'll never know that the task failed, so your code can't take any recovery action. - [Bill] And that's what we saw in that first application. When it got kind of wibbly wobbly. Okay, so let's see what happens once we add the await. So we fixed this, we've dealt with our warnings, I click it once, works beautifully. Of course I was being nice to it. - [Mika] It seems to work the same. - [Bill] Now, if we start clicking it a few more times, uh oh. - [Mika] Yeah, that just seemed harsh, it just crashed. - [Bill] Right, so what's happening now is because I'm awaiting the task, and when a task fails, if you look a little bit below it that run animation, async, it's got some code that says if an animation is already running, meaning the size isn't its original size, well then we're going to throw an invalid operation exception. So that means this task fails. And that means that when I await it, this invalid operation exception gets thrown into the calling context. And in an event handler, if it throws an exception, well WPF just says, I don't know what went wrong. The best thing to do is just close the application before doing any more damage. - [Mika] Right, so what do I do when I must write an async void method? - [Bill] Well, so when you must write one, now I'm responsible for cleaning up here, in this async void method. And I have to say, I'm going to put this in a try and then I'm going to catch just that specific exception because I know how to recover from that invalid operation exception. I can say just it's okay, don't do anything, don't start a second animation, and then it should be safe But I'm only catching that one, not all exceptions, because that would be really dangerous. So now I'll try it. And again, if I behave nicely, oh, it's going to work. It's always worked, then. And then, but if I start frantically pressing that button you know, nothing bad happens. It runs the egg animation once, doesn't try to start other ones, we don't get the wibbly wobbly stuff and it doesn't crash. - [Mika] What if I don't care if an action finishes or not? - [Bill] Then you would go back to that, not await in the task, but you have to understand the risks. You know, it might be safe if it's something like say logging after an error, right? I had some error I'm going to try to write to a log and that's an async operation. If I can't write about the error, well maybe I don't really care that it failed and I couldn't write it but maybe I'd probably want to terminate the program anyway because of the original exception. But otherwise, the best course of action if you can't recover, is to let the program fail and stop doing any further damage. - [Mika] So you can actually print that exception. - [Bill] Right, instead of that empty block, I could do something like, say, I could say message box dot show, 'cause this is a WPF application and I could say, please stop clicking. And now if somebody starts frantically clicking, they'll start getting that message box. - Cool, so we just spoke about handling asynchronous errors, in our next video we're going to talk about asynchronous and threading.

Contents