When the async method is started, it captures the current synchronization context. A way to solve this issue is to create your own synchronization context which captures the exception.
The point here is that the synchronization context posts the callback to the thread pool, but with a try/catch around it:
public class AsyncSynchronizationContext : SynchronizationContext
{
public override void Send(SendOrPostCallback d, object state)
{
try
{
d(state);
}
catch (Exception ex)
{
// Put your exception handling logic here.
Console.WriteLine(ex.Message);
}
}
public override void Post(SendOrPostCallback d, object state)
{
try
{
d(state);
}
catch (Exception ex)
{
// Put your exception handling logic here.
Console.WriteLine(ex.Message);
}
}
}
In the catch above you can put your exception handling logic.
Next, on every thread (SynchronizationContext.Current is [ThreadStatic]) where you want to execute async methods with this mechanism, you must set the current synchronization context:
SynchronizationContext.SetSynchronizationContext(new AsyncSynchronizationContext());
The complete Main example:
class Program
{
static void Main(string[] args)
{
SynchronizationContext.SetSynchronizationContext(new AsyncSynchronizationContext());
ExecuteAsyncMethod();
Console.ReadKey();
}
private static async void ExecuteAsyncMethod()
{
await AsyncMethod();
}
private static async Task AsyncMethod()
{
throw new Exception("Exception from async");
}
}