为什么不抛出这个异常? [英] Why doesn't this exception get thrown?

查看:151
本文介绍了为什么不抛出这个异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 我有时会使用一组任务,为了确保他们都在等待着我> public async任务ReleaseAsync(params Task [] TaskArray)
{
var tasks = new HashSet< Task>(TaskArray);
while(tasks.Any())tasks.Remove(await Task.WhenAny(tasks));
}

然后调用如下:

 等待ReleaseAsync(task1,task2,task3); 
//或
等待ReleaseAsync(tasks.ToArray());

然而,最近我一直在注意到一些奇怪的行为,并设置看是否有问题ReleaseAsync方法。我设法把它缩小到这个简单的演示,它运行在linqpad,如果你包括 System.Threading.Tasks 。它也将在控制台应用程序或asp.net mvc控制器中稍微修改。

  async void Main()
{
任务[] TaskArray = new Task [] {run()};
var tasks = new HashSet< Task>(TaskArray);
while(tasks.Any< Task>())tasks.Remove(await Task.WhenAny(tasks));
}

public async任务< int> run()
{
return await Task.Run(()=> {
Console.WriteLine(started);
throw new Exception(broke);
Console.WriteLine(complete);
return 5;
});
}

我不明白是为什么Exception从不出现在任何地方。我会想到,如果有例外的任务等待,它会抛出。我可以用这样一个简单的替换while循环来确认:

  foreach(TaskArray中的var task) 
{
等待任务; //这将正确抛出异常
}


$ b $我的问题是,为什么显示的例子不正确地抛出异常(它永远不会显示在任何地方)。

解决方案

p> TL; DR run()抛出异常,但您正在等待 WhenAny(),它不会抛出异常。






WhenAny 指出:


当任何提供的任务已完成时,返回的任务将完成。返回的任务将始终以 RanToCompletion 状态结束,其结果设置为要完成的第一个任务。即使第一项任务要完成,请在已取消已故状态结束。


基本上发生的是,由 WhenAny 返回的任务简单地吞下了故障的任务。它只关心任务完成的事实,而不是它已经成功完成。等待任务时,它完全没有错误地完成,因为它是内部的任务发生故障,而不是您正在等待的内部任务。


I use a set of tasks at times, and in order to make sure they are all awaited I use this approach:

public async Task ReleaseAsync(params Task[] TaskArray)
{
  var tasks = new HashSet<Task>(TaskArray);
  while (tasks.Any()) tasks.Remove(await Task.WhenAny(tasks));
}

and then call it like this:

await ReleaseAsync(task1, task2, task3);
//or
await ReleaseAsync(tasks.ToArray());

However, recently I have been noticing some strange behavior and set to see if there was a problem with the ReleaseAsync method. I managed to narrow it down to this simple demo, it runs in linqpad if you include System.Threading.Tasks. It will also work slightly modified in a console app or in an asp.net mvc controller.

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;
 });
}

What I don't understand is why the Exception never shows up anywhere. I would have figured that if the Tasks with the exception were awaited, it would throw. I was able to confirm this by replacing the while loop with a simple for each like this:

foreach( var task in TaskArray )
{
  await task;//this will throw the exception properly
}

My question is, why doesn't the shown example throw the exception properly (it never shows up anywhere).

解决方案

TL;DR: run() throws the exception, but you're awaiting WhenAny(), which doesn't throw an exception itself.


The MSDN documentation for WhenAny states:

The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state.

Essentially what is happening is that the task returned by WhenAny simply swallows the faulted task. It only cares about the fact that the task is finished, not that it has successfully completed. When you await the task, it simply completes without error, because it is the internal task that has faulted, and not the one you're awaiting.

这篇关于为什么不抛出这个异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆