示例代码如下:
Action action = async () =>
{
Console.WriteLine("Action start...");
await Task.Delay(1000);
throw new Exception("Exception from an async action");
};
Task.Run(action);
Console.ReadKey();
处理异常的位置?
答案 0 :(得分:2)
您可以在任务本身内部或外部由调用者处理它,只需记住在Task.Run上等待,这可以确保您捕获异常而不是使其成为无声死亡。
lines = LOAD 'abc_doc1.txt';
words = FOREACH lines GENERATE word;
C = GROUP words all;
lines1 = LOAD 'abc_doc2.txt';
words1 = FOREACH lines GENERATE word;
C1 = GROUP words1 all;
D = foreach C1 generate $0 as searchwrd
E= Filter D by (searchwrd!=(foreach C generate $0))
另外,请检查此post有关异步/等待异常处理的差异
答案 1 :(得分: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");
};
第二个错误是它在线程池上运行委托时使用了fire-and-forget。 &#34;忘了&#34; &#34;“即发即忘”的一部分&#34;意味着&#34;忽略所有异常&#34;。要正确传播异常,应等待Task.Run
返回的任务(有关await
如何处理任务的详细信息,请参阅我的blog post on async and await):
await Task.Run(action);
答案 2 :(得分:0)
由于您使用Task.Run(action);
并且您没有等待返回的任务对象,异常将在另一个线程中抛出,您无法在调用方线程中处理它(使用{ {1}}例如);
然后您需要在Action委托中处理异常:
ContinueWith
答案 3 :(得分:0)
人们常常认为,当使用async-await时会涉及多个线程,而实际上并非如此,除非您指定这样做。
在中间某处读取Eric Lippert about async-await搜索异步等待。
他比较异步等待与厨师:在烘烤面包时,他可以等到面包在烤开水前喝茶和鸡蛋。如果他开始开水然后回头看看面包是否烤过,效率会更高。
您的代码也会发生同样的情况。在 await task.Delay 期间,您的线程不会开始等待。相反,它会调高其调用堆栈以查看其中一个调用者(所有调用者都必须异步!)是否正在等待,因此可以继续处理而不会调用其结果。一段时间后,它返回以查看Task.Delay是否已完成并继续下一个抛出异常的语句。
请注意,在这种情况下,只涉及一个线程。所有其他异常捕获都会执行异常捕获。尽管捕获器可以检查调用堆栈,但他不确定执行哪些代码以及哪些代码不是。在这方面,与非async-await
没有太大区别