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
它。内部任务已成为一劳永逸的任务。
我读到了 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
它。内部任务已成为一劳永逸的任务。