Basically, with async/await
you can follow the same pattern you do for synchronous programming. Don't handle exceptions inside every async
method, unless absolutely required. Handle them on the topmost level, i.e., inside the outermost async or synchronous method. What's this method is depends on the execution environment.
E.g., it might be an async void
event handler in case it's a UI app:
async Task DoWorkAsync()
{
// don't handle exceptions here
}
async void Form_Load(object s, EventArgs args)
{
try {
await DoWorkAsync();
}
catch (Exception ex)
{
// log
logger.Error(ex);
// report
MessageBox.Show(ex.Message);
}
}
Or, it may be the Main
entry point of a console app:
static void Main(string[] args)
{
try {
DoWorkAsync().Wait();
}
catch (Exception ex)
{
// log
logger.Error(ex);
throw; // re-throw to terminate
}
}
You should understand though how exceptions get propagated for async
methods. Check this for some more details.
Also, not all exceptions are the same and should be handled equally. Check Eric Lippert's "Vexing exceptions".