c# - 为什么不抛出这个异常?

标签 c# .net exception async-await task

我有时使用一组任务,为了确保它们都在等待我使用这种方法:

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

然后这样调用它:

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

但是,最近我注意到一些奇怪的行为,并设置查看 ReleaseAsync 方法是否有问题。我设法将它缩小到这个简单的演示,如果您包含 System.Threading.Tasks,它会在 linqpad 中运行。它还可以在控制台应用程序或 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;
 });
}

我不明白的是为什么 Exception 永远不会出现在任何地方。我本以为如果等待有异常的任务,它就会抛出。我能够通过用这样的简单 for each 替换 while 循环来确认这一点:

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

我的问题是,为什么显示的示例没有正确抛出异常(它从未出现在任何地方)。

最佳答案

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


WhenAny 的 MSDN 文档状态:

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.

本质上发生的事情是 WhenAny 返回的任务简单地吞下了错误的任务。它只关心任务完成的事实,而不关心它是否已经成功完成。当您 await 任务时,它会无误地完成,因为它是内部任务出现故障,而不是您正在等待的任务。

关于c# - 为什么不抛出这个异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23766808/

相关文章:

c# - 忽略 C# 命令行程序中的 try block

c# - 在行命令中获取 Gridview 的内容

c# - 什么解码了我的编码哈希符号 (%23)?

.net - 为什么 "Non"中的 "ExecuteNonQuery"?

用于检查重复行和重复列的 Python 错误日志记录

c# - C# 中的类型初始化异常

c++ - 多个字符串异常处理

c# - 继承类的泥潭,如何让这段可维护的代码

c# - 将表单数据和文件发布到 ASP.NET Web API

c# - 请告诉我一个为委托(delegate)(或)函数指针显示 `need` 的情况