Task.Run vs Task.Factory.StartNew - 预期的死锁没有发生

Task.Run vs Task.Factory.StartNew - Expected Deadlock is not happening

我读到了 Task.Run 和 Task.Factory.StartNew 的区别。

Task.Run(() => {});

应该等同于

Task.Factory.StartNew(() => {}, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

但在我的代码中,我预计死锁不会发生,因为 Task.Factory.StartNew:

private Task backgroundTask;

private async Task DoSomethingAsync()
{
   // this should deadlock
   await this.backgroundTask.ConfigureAwait(false);
   throw new Exception();
}

private async Task Test()
{
   this.backgroundTask = Task.Factory.StartNew(async () =>
      {
         await this.DoSomethingAsync().ConfigureAwait(false);
      }, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

   // just wait here for testing/debugging
   await Task.Delay(10000).ConfigureAwait(false);
   // if no deadlock, this should throw
   await this.backgroundTask.ConfigureAwait(false);
}

但这不是僵局。 DoSomethingAsync 中的异常被抛出但从未被捕获。 在 Task.Delay 之后等待任务也不抛出,因为它是 RanToCompletion。

当使用 Task.Run 时,如预期的那样死锁:

private Task backgroundTask;

private async Task DoSomethingAsync()
{
   // this is deadlocking
   await this.backgroundTask.ConfigureAwait(false);
   throw new Exception();
}

private async Task Test()
{
   this.backgroundTask= Task.Run(async () =>
      {
         await this.DoSomethingAsync().ConfigureAwait(false);
      });

   // just wait here for testing/debugging
   await Task.Delay(10000).ConfigureAwait(false);
   // never reached because of deadlock
   await this.backgroundTask.ConfigureAwait(false);
}

任何人都可以解释这种行为吗?

方法 Task.Factory.StartNew 与异步委托一起使用时 returns 嵌套任务:Task<Task>。您正在将此嵌套任务分配给 Task 类型的变量,这是允许的,因为 class Task<TResult> 派生自 class Task。然后发生的事情是你失去了对内部任务的引用,所以你没有办法等待它。当你await this.backgroundTask你在等待外层Task<Task>,但是你不能得到等待操作的结果,它是一个Task,内层Task,和await它。内部任务已成为一劳永逸的任务。