2016-07-21 2 views

ответ

1

В коде есть две вещи.

Во-первых, используется делегат async void, который предотвращает нормальное функционирование исключений (для получения дополнительной информации об избежании async void см. my MSDN article on async best practices). Необходимо использовать Func<Task> вместо Action (для получения дополнительной информации о асинхронных дружественных типах делегатов см my blog post on synchronous and asynchronous delegate types):

Func<Task> action = async() => 
{ 
    Console.WriteLine("Action start..."); 
    await Task.Delay(1000); 
    throw new Exception("Exception from an async action"); 
}; 

Второй вещь неправильно, что это с помощью огня и забыть при работе делегата на резьбе бассейн. «Забытая» часть «огня и забывания» означает «игнорировать все исключения».Чтобы правильно размножать исключения, задача возвращается из Task.Run должна ожидаться (для получения дополнительной информации о том, как await работы с задачами, см мой blog post on async and await):

await Task.Run(action); 
+0

Да, вы правы. На самом деле, я прочитал вашу статью, прежде чем я разместил здесь. Проблема в том, что мне нужно написать метод, чтобы принять экземпляр Action в качестве параметра и выполнить его с помощью задачи. Я не нашел способ избежать необработанных исключений, из-за которых мой код разбился. – Wang

+0

@Wang: Если тип * имеет * действие 'Action' (синхронно), а реализация * имеет * асинхронную, что является очень редкой позицией, то вам просто нужно поймать все исключения в пределах вашего выражения лямбды. –

0

С вашей помощью Task.Run(action); и вы не в ожидании объекта задача вернулся, исключение в другом потоке, и вы не можете справиться с этим в потоке вызывающего абонента (с использованием ContinueWith, например);

Затем Вам нужно обработать исключение внутри действий делегата:

Action action = async() => 
{ 
    try 
    { 
     Console.WriteLine("Action start..."); 
     await Task.Delay(1000); 
     throw new Exception("Exception from an async action"); 
    } 
    catch(Exception ex) 
    { 
     // do something 
    } 
}; 
2

Вы можете обрабатывать ее внутри самой задачи или вне вызывающего, просто возражает AWAIT на Task.Run, это гарантирует, что вы поймать исключение вместо того, чтобы это молчаливое death.`

Func<Task> action = async() => 
{ 
    Console.WriteLine("Action start..."); 
    await Task.Delay(1000); 
    throw new Exception("Exception from an async action"); 
}; 

try 
{ 
    await Task.Run(action); 
} 
catch(Exception ex) 
{ 
    Console.WriteLine(ex.Message); 
} 

Console.ReadKey(); 

Кроме того, проверьте этот post о различиях в асинхронном/ждут обработки исключений

+0

Но ОП не ждать 'Task'. – user3185569

+1

Ни он, ни стараюсь/поймать, вот почему мы предоставляем ему ответы, верно? –

+1

Вы выполнили свой код? Я бы не опубликовал его, если бы это было легко разрешено. – Wang

0

Нередко люди думают, что при использовании async-ожидания задействованы несколько потоков, в то время как на самом деле это не так, если вы не указали это.

Прочитано Eric Lippert about async-await искать где-то посередине для асинхронного ожидания.

Он сравнивает асинхронные ожидания с поваром: при поджаривании хлеба он может подождать, пока хлеб не поджарится перед кипячением воды для чая и яиц. Было бы более эффективно, если бы он начал кипятить воду, а затем повернуть назад, чтобы узнать, поджарен ли хлеб.

То же самое происходит в вашем коде. Во время вашего ждут task.Delay ваш поток не начинает ждать. Вместо этого он поднимается вверх по стеку вызовов, чтобы узнать, не ожидает ли один из вызывающих абонентов (кто все должен быть асинхронным!), И таким образом может продолжить обработку без результата своих вызовов. Через некоторое время он вернется, чтобы узнать, завершен ли Task.Delay и продолжает ли следующий оператор, где генерируется исключение.

Обратите внимание, что в этом сценарии задействован только один поток. Захват исключений выполняется как все остальные исключения. Хотя зрелище может проверять стек вызовов, он не уверен, какие части кода выполняются, а какие нет. В этом отношении нет большой разницы с не-асинхронным ожиданием

Смежные вопросы