You can get these semantics through the use of await
. It when you await
something it will schedule the remainder of the method as a continuation of the previous method, meaning that the operation is performed asynchronously. However, when the awaited operation finishes, if it represents something that throws an exception, that exception will be caught and then re-thrown within the context of your next continuation, allowing you to wrap a series of asynchronous operations in a single try/catch
, having the syntax and semantics you desire. A simple example might look like:
public static async Task Foo()
{
try
{
await Task.Run(() => DoSomething());
await Task.Run(() => DoSomethingElse());
}
catch(Exception e)
{
Console.WriteLine(e);
}
}
Here DoSomething
and DoSomethingElse
will be run in a thread pool thread, and if either throws an exception when running, not when being started, then the catch
block will be hit.