I'm basically wondering how I should, in C#, catch exceptions from asynchronous methods that are waited on through the await
keyword. Consider for example the following small console program, which most importantly contains a method called AwaitSync
. AwaitSync
calls TestAsync
, which returns a Task that when executed throws an exception. I try to catch the exception in AwaitAsync
, but it goes unhandled.
class Program
{
static void Main(string[] args)
{
AwaitAsync();
Console.ReadKey();
}
static async Task AwaitAsync()
{
try
{
await TestAsync();
}
catch (Exception)
{
Console.WriteLine("Exception caught");
}
}
static Task TestAsync()
{
return Task.Factory.StartNew(() => { throw new Exception("Test"); });
}
}
How am I supposed to go about catching the exception from the Task returned by TestAsync
? While this example is a console program, my real life problem is within the context of of ASP.NET MVC / Web API.
EDIT:
Turns out the exception is getting caught, for technical reasons I just didn't notice the 'Exception caught' message before the terminal closed. In any case, Jon Skeet's answer was very valuable to my understanding of await
and exception handling.
It uses a long jump out of the current function to the try block. The try block then uses an if/else to skip the code block to the catch block which check the local variable to see if it should catch. This uses a global pointer so the longjmp() knows what try was last run.
The C# try and catch keywords are used to define a try catch block. A try catch block is placed around code that could throw an exception. If an exception is thrown, this try catch block will handle the exception to ensure that the application does not cause an unhandled exception, user error, or crash the application.
The try-except statement is a Microsoft extension to the C language that enables applications to gain control of a program when events that normally terminate execution occur. Such events are called exceptions, and the mechanism that deals with exceptions is called structured exception handling.
The catch statement allows you to define a block of code to be executed, if an error occurs in the try block.
The code generated for the await
expression will call GetResult()
on the TaskAwaiter
associated with the Task
returned by TestAsync
.
GetResult
will notice that the task is faulted, fetch the first exception from the AggregateException
within the task, and throw that.
The net result is that your catch block will catch the exception thrown in your task - but if you await a task which has multiple exceptions, you'll only see the first one unless you take special actions (there are various approaches to this).
As you're claiming the exception actually goes unhandled, it seems there's something in your code other than what you're showing - as the code you've given should certainly work, and does for me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With