等待空任务永远旋转(等待新任务(()=> {}))

Phi*_*tle 10 .net c# asynchronous task async-await

我试图了解这段代码:

 [TestFixture]
 public class ExampleTest
 {
    [Test]
    public void Example()
    {
        AwaitEmptyTask().Wait();
    }

    public async Task AwaitEmptyTask()
    {
        await new Task(() => { });
    }
 }
Run Code Online (Sandbox Code Playgroud)

该方法Example永远不会结束并永久阻止. 为什么??

修复(从返回在异步单元测试方法成株任务)是取代await new Task( () => {})return Task.FromResult<object>(null);但同样的,为什么是这个必要吗?

我知道有一堆类似于这个的问题,但我见过的没有一个似乎解释了为什么会发生这种情况:

Ser*_*rvy 18

你正在创建一个任务并且永远不会启动它,所以它永远不会完成.

您应该使用Task.Run创建要立即开始执行的任务,而不是使用Task构造函数.

  • `await` 关键字不是启动任务吗? (2认同)
  • 它附加了任务的延续。而已。你可以从你自己的代码中看出它显然*不*启动任务。如果是这样,那么您的代码实际上会完成。 (2认同)
  • @PhilipPittle没有理由不能为未启动的任务添加延续.它无法知道你从未打算开始任务.它假设如果你要为一个未启动的任务添加一个延续,你最终会启动它,如果你想在某个时刻继续运行.通过使用构造函数,你不停地说:"我不想让它开始,但不要担心,我会在最新的时候开始你".如果那不是您想要发生的,那么您不应该使用构造函数. (2认同)

SLa*_*aks 8

你需要打电话Start()给你的任务.

否则,它永远不会完成.


bor*_*egg 6

即使你把它改成了

await Task.Run(() => { });
Run Code Online (Sandbox Code Playgroud)

它可能仍然永远不会完成.当您点击此行时,程序会创建一个继续任务,该任务将在任务完成时继续.任务为空的事实无关紧要.此时,控制流程又回到了

AwaitEmptyTask().Wait();
Run Code Online (Sandbox Code Playgroud)

等待任务完成并阻止当前线程.

任务完成后,它会尝试继续当前线程.但是,它不能,因为线程被Wait()调用阻止.

将等待的行更改为

await Task.Run(() => { }).ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)

这是一个常见的死锁问题.不要混合Wait()和等待.请参阅http://msdn.microsoft.com/en-us/magazine/jj991977.aspx

  • @PhilipPittle它将继续任务配置为在任何可用线程上继续.默认情况下,它将尝试继续在同一个线程上,因此出现上述问题. (2认同)