【问题标题】:Task await confusion任务等待混乱
【发布时间】:2016-04-07 03:50:09
【问题描述】:

我有以下

async void A () {
  await B();
}

async Task B () {
  await Task.Factory.StratNew( ()=> C());
}

async Task C () {
  while (true) {
    //await Task.Factory.StartNew(()=> {Thread.Sleep(5000);});
    Thread.Sleep(5000);
  }
}

在上面的程序中,A 永远不会返回,因为 C 中的 while 循环。但是,如果我取消注释 C 和 KEEP Thread.Sleep(5000) 内的行,A 会立即返回。有人可以解释那里发生了什么吗?

【问题讨论】:

  • 当您取消注释该行时,您也会注释掉 Thread.Sleep(5000);对吗?
  • @rbaghbanli 不,我没有
  • StartNew is dangerous,您可能最终会在 UI 线程上运行代码,但您不希望它会这样,请改用 Task.Run。

标签: c# asynchronous async-await task


【解决方案1】:

主要问题在文章Task.Run vs Task.Factory.StartNew中进行了详尽的描述。如果您要像这样更改代码,您会看到我所期望的。

async void A()
{
    await B(); 
}

async Task B()
{
    // await Task.Factory.StartNew(() => C());
    await Task.Run(async () => await C());
    // await Task.Run(() => C()); // this would still produce the same effect
}

async Task C()
{
    while (true)
    {
        await Task.Delay(5000);
        //Thread.Sleep(5000);
    }
}

另见previous answer by Stephen Cleary。本质上Task.Factory.StartNew 不尊重async/await 模型,您确实应该将Task.Runasync/await 代码一起使用。 Task.Factory.StartNew 创建并启动一个新任务,而无需实际等待结果,但返回的任务同步执行时除外,这是在您删除 C 内部的等待时发生的。

【讨论】:

  • commentedA 永远不会返回,uncommentedA 会立即返回。我认为你的解释是相反的。
  • @MonsterHunter - 谢谢!我对这个问题进行了更深入的研究,答案与Task.Factory.StartNew 以及它不应该用于async/await 的原因有关,因为它是最初为并行开发而不是为创建的async/await 框架而开发的TPL 库稍后。
【解决方案2】:

当您在无限循环内部有“等待”时,运行时会中断无限循环,让执行外部调用,从而有机会完成 B(以及因此 A)然后返回到无限循环。

没有“等待”,B(因此 A)无法完成,他们将永远“等待”。

【讨论】:

  • 那么对于未注释的行,B 仍应暂停 5 秒,因为在最内部的 await 中的 Thread.Sleep(5000),对吧?但是A 只是立即返回。
  • 错了。异步调用一直返回到 A,因为所有调用都是异步的。所以,基本上 A 在它开始等待 5 秒之前就完成了 :)
  • 我想我的困惑是await 确保AB 完成之前不会返回。 B 在线程运行 C 完成之前不会返回。 C 永远不会返回,内部的await 只是让进程。我的逻辑有什么问题?
  • @MonsterHunter 你的逻辑有问题的是,A、B 和 C 在遇到第一个 await 时都会立即返回,其任务将代表其余代码完成后进入Completed 状态。因为您的第一个 C 中没有 await,所以它永远不会返回。而且因为 C 永远不会返回,B 永远不会等待它,并且因为 B 永远不会等待它,所以它也永远不会返回。你应该得到一个关于 C 的编译器警告,它是一个没有 await 的异步方法。
猜你喜欢
  • 2020-09-14
  • 1970-01-01
  • 2013-03-10
  • 1970-01-01
  • 2014-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-06
相关资源
最近更新 更多