【问题标题】:Await doesn't block calling thread [duplicate]等待不会阻止调用线程[重复]
【发布时间】:2020-06-30 06:24:32
【问题描述】:

我从来没有机会深入了解 async/await ,所以我只是大致了解它的作用。

所以我在 WinForms 应用程序中这样尝试:

private async void button2_Click(object sender, EventArgs e)
{
  // In below line I understand the Task is created and scheduled to execute, which in this
  // simple case means, that it executes right away asynchronously.
  var task = Task.Factory.StartNew(() =>
  {
    Task.Delay(5000).Wait();
    return 12;
  });

  // Here we wait for the task to finish, so we don't see MessageBox yet.
  var res = await task;
  MessageBox.Show("Result is :" + res);
}

我的问题是,因为我们正在等待await,所以我希望阻止 UI 线程,因为我们可以在该线程中走得更远(到 MessageBox 的行)。所以 UI 线程实际上会在带有 event hadnler 的方法上停止。

但是,令我惊讶的是,windows 是响应式的,一切都运行良好,但我没想到会这样。谁能解释一下这是怎么回事?

看完this post后,我还是有疑问,如果await是异步的,在我的例子中没有阻塞UI线程,为什么线程不继续到下一行MessageBox?那么 UI 线程如何进行呢?

await 之后的代码只是另一个Task,就像在ContinueWith 中一样,这是个好主意吗?但它又回到了 UI 上下文?

【问题讨论】:

  • async void 表示 UI 线程不等待它。
  • "windows 响应迅速,一切运行良好,但我没想到" -- 然而,正是 await 的点。该方法在该点返回,并在等待的对象完成后恢复执行。与此同时,该线程被释放以做它想做的任何其他事情。这是 async/await 如何工作的基本,我们在网站上有很多问题(数百,如果不是数千)已经很好地解释了所有这些。请参阅标记为重复的最引用/最彻底的之一。
  • 我绝不是异步专家,但据我了解,一旦您的异步方法中的代码到达await关键字,流程将返回调用方法,直到等待的任务完成,然后流程才会恢复到异步方法的其余部分。
  • await 不是Wait。当代码遇到await 关键字时,该方法会在注册一个延续到可等待对象的完成后立即返回。延续包含await 行下方的任何内容。在您的情况下,它包含 MessageBox.Show 命令。当 awaitable 完成时,注册的 continuation 将运行。
  • 如果不是简洁的await 有一个更具描述性的名称,例如continueAfterCompletionOf,那么这个运算符可能不会那么混乱。当然,这么长的关键字会有其他缺点。 ??????

标签: c# async-await


【解决方案1】:

异步方法很像生成器方法。编译器将在每个 await 运算符处拆分您的代码。插入一个代码块来检查任务是否已经完成,在这种情况下,该方法立即继续。或者如果任务没有完成,注册一个回调以便稍后继续执行,然后你的方法返回。

提前返回是异步方法的重点。

【讨论】:

    猜你喜欢
    • 2020-01-17
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-21
    相关资源
    最近更新 更多