Поймать необработанные исключения из async
когда async метод, ожидаемый при выбрасывании исключения, исключение сохраняется где-то и выбрасывание его задерживается. В приложении WinForms или WPF он использует SynchronizationContext.Current постить исключениями. Однако, например, в консольном приложении, он создает исключение в пуле потоков и сбрасывает приложение.
как я могу предотвратить исключения из async способ вывести из строя заявление?
EDIT:
по-видимому, проблема, которую я описываю, заключается в том, что у меня есть void async методы. См. комментарии.
2 ответов
как я могу предотвратить исключения из асинхронного метода от приведения приложения?
следуйте этим рекомендациям:
- все 
asyncметоды должны возвращатьTaskилиTask<T>если они не есть вернутьсяvoid(например, обработчики событий). - в какой-то момент, Вы должны 
awaitвсеTasks вернулся изasyncметоды. Единственная причина, по которой ты не хочешь этого делать, это если ты не ... дольше заботиться о результате операции (например, после ее отмены). - Если вам нужно поймать исключение из 
async voidобработчик событий, а затем поймать его в обработчике событий-точно так же, как вы сделали бы, если бы это был синхронный код. 
вы можете найти меня async / await интро в должности полезно; я охватываю несколько других лучших практик там, а также.
когда async метод запущен, он захватывает текущий контекст синхронизации. Способ решения этой проблемы-создать собственный контекст синхронизации, который фиксирует исключение.
дело в том, что контекст синхронизации отправляет обратный вызов в пул потоков, но с try / catch вокруг него:
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);
        }
    }
}
на catch выше вы можете поместить логику обработки исключений.
далее на каждую нить (SynchronizationContext.Current is [ThreadStatic]) где вы хотите выполнить async методы с помощью этого механизма вы должны установить текущий контекст синхронизации:
SynchronizationContext.SetSynchronizationContext(new AsyncSynchronizationContext());
полное Main пример:
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");
    }
}