Reputation: 974
When I call an async method and get a task back, will that immediately throw or will it wait until I await the task?
In other words, will this code work? Or will I have to wrap the method call in the try-block as well?
Task task = ThisMethodWillThrow();
try
{
await task;
}
catch (Exception e)
{
Console.WriteLine("oops");
}
Upvotes: 9
Views: 1949
Reputation: 1063774
Both are possible. If the method is actually async
(i.e. uses the C# async
keyword in the declaration), then the C# compiler wraps it up in such a way that it will always reliably throw on the await
, but it is important to note that this is not the only way to write a method that can be await
-ed, so: if you don't control the method being called (ThisMethodWillThrow
) and can't rely on knowledge of the implementation, it would be better for the try
to include the initial invoke, as well as the await
.
As an example of a method that will throw immediately rather than in the await
:
Task ThisMethodWillThrow() { // note that this is **not** "async", but is awaitable
if (thingsAreBad) throw new SomeException();
return SomeInnerMethod();
}
async Task SomeInnerMethod() { ... }
It might be tempting to think "well, just make all awaitable methods async
, to avoid this" - like:
async Task ThisMethodWillThrowToo() { // note that this is "async"
if (thingsAreBad) throw new SomeException();
await SomeInnerMethod();
}
However: there are scenarios where the async machinery is a very measurable performance overhead in the "often sync, sometimes async" case - and so a common optimization in performance critical awaitable code (IO/network code, for example) is to actively avoid the async
machinery unless we know that we're actually falling into the asynchronous path.
Upvotes: 14