为什么带有异常的异步任务会成功完成?

Dev*_*Dev 1 c# asynchronous

我有一个 C# 控制台应用程序,其中包含许多异步任务。其中一项任务是抛出异常。但是,我了解到主机代码没有按预期处理该场景。为了了解发生了什么,我决定进行一个测试。此测试的目的是创建一个Task异步运行的程序,但故意抛出异常。我想看看返回的内容是否符合主机代码的预期。

令我惊讶的是,该Task对象的IsCompletedSuccessfully属性是trueIsFaulted属性是false。然而,我期待IsCompletedSuccessfully成为false并且IsFaulted成为true。代码如下所示:

[Fact]
public void Repro()
{
  var task = new Task(async () => {
    var operand1 = 2;
    var operand2 = 0;
    var result = operand1 / operand2;
    
    Thread.Sleep(250);
    await Task.CompletedTask;
  });
  
  task.RunSynchronously();
  
  Console.WriteLine($"Cancelled: {task.IsCanceled}, Completed: {task.IsCompleted}, Completed Successfully: {task.IsCompletedSuccessfully}, Faulted: {task.IsFaulted}");
  if (task.Exception != null)
  {
    Console.WriteLine("There was an exception");
  }

  Assert.Equal(false, task.IsCompletedSuccessfully);
  Assert.Equal(true, task.IsFaulted);
}
Run Code Online (Sandbox Code Playgroud)

为什么/如何成功完成此任务?为什么它没有毛病呢?我预计它会抛出除以零的异常。

谢谢。

can*_*on7 5

没有Task接受 a 的构造函数Func<Task>唯一的重载接受Actionor Action<object>

因此,当您编写 时new Task(async () => ...),那里的异步 lambda 需要编译为async void方法。

请注意void:没有办法将Task备份传播给调用者,这意味着Task构造函数new Task(...)只能在 lambda 直接抛出异常时才知道是否存在异常。然而,由于 lambda 是async void,它不会向调用者抛出异常!但是,它会将它们重新扔到线程池中,这将使您的应用程序崩溃。