Tra*_*s J 8 .net c# exception task async-await
我有时会使用一组任务,为了确保它们都在等待我使用这种方法:
public async Task ReleaseAsync(params Task[] TaskArray)
{
var tasks = new HashSet<Task>(TaskArray);
while (tasks.Any()) tasks.Remove(await Task.WhenAny(tasks));
}
Run Code Online (Sandbox Code Playgroud)
然后像这样调用它:
await ReleaseAsync(task1, task2, task3);
//or
await ReleaseAsync(tasks.ToArray());
Run Code Online (Sandbox Code Playgroud)
但是,最近我注意到了一些奇怪的行为,并设置了ReleaseAsync方法是否存在问题.我设法将它缩小到这个简单的演示,如果你包含它,它将在linqpad中运行System.Threading.Tasks.它也可以在控制台应用程序或asp.net mvc控制器中稍作修改.
async void Main()
{
Task[] TaskArray = new Task[]{run()};
var tasks = new HashSet<Task>(TaskArray);
while (tasks.Any<Task>()) tasks.Remove(await Task.WhenAny(tasks));
}
public async Task<int> run()
{
return await Task.Run(() => {
Console.WriteLine("started");
throw new Exception("broke");
Console.WriteLine("complete");
return 5;
});
}
Run Code Online (Sandbox Code Playgroud)
我不明白为什么异常永远不会出现在任何地方.我想如果等待具有异常的任务,它就会抛出.我能够通过用这样的简单替换while循环来确认这一点:
foreach( var task in TaskArray )
{
await task;//this will throw the exception properly
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,为什么显示的示例没有正确抛出异常(它永远不会出现在任何地方).
Yuv*_*kov 10
一个Task不是awaited或不使用它Wait()或Result()方法,将默认吞例外.这种行为可以通过崩溃运行过程一旦Task被GC'd 修改回原来在.NET 4.0中完成的方式.您可以app.config按如下方式设置它:
<configuration>
<runtime>
<ThrowUnobservedTaskExceptions enabled="true"/>
</runtime>
</configuration>
Run Code Online (Sandbox Code Playgroud)
微软并行编程团队在这篇博文中的引用:
那些熟悉.NET 4中的任务的人会知道TPL具有"未观察到的"异常的概念.这是TPL中两个竞争设计目标之间的折衷:支持将未处理的异常从异步操作封送到消耗其完成/输出的代码,并遵循标准的.NET异常升级策略来处理应用程序代码未处理的异常.从.NET 2.0开始,在新创建的线程,ThreadPool工作项等中未处理的异常都会导致默认的异常升级行为,这会导致进程崩溃.这通常是可取的,因为异常表明出现了问题,并且崩溃有助于开发人员立即识别应用程序已进入不可靠状态.理想情况下,任务将遵循相同的行为.但是,任务用于表示稍后加入的异步操作,如果这些异步操作产生异常,则应将这些异常封送到加入代码的运行位置并消耗异步操作的结果.这固有地意味着TPL需要支持这些异常并保持它们,直到消费代码访问任务时它们可以被再次抛出.由于这会阻止默认升级策略,因此.NET 4应用了"未观察到的"异常的概念来补充"未处理"异常的概念."未观察到的"异常是存储在任务中但从未以消费代码以任何方式查看的异常.有很多方法可以观察异常,包括Wait()on the Task,访问Task的Result,查看Task的Exception属性,等等.如果代码从未观察到Task的异常,那么当Task消失时,会引发TaskScheduler.UnobservedTaskException,为应用程序提供一个"观察"异常的机会.如果异常仍未被观察到,则异常升级策略将由终结器线程上未处理的异常启用.
| 归档时间: |
|
| 查看次数: |
1838 次 |
| 最近记录: |