Use async await or task?

本文关键字:task or await async Use | 更新日期: 2023-09-27 18:14:36

您已经构建了一个复杂的计算算法。它需要相当长的时间来完成,您希望确保您的应用程序保持响应。你是怎么做的?

  • 。使用异步/等待。
  • B。同步运行代码。
  • C。使用Task.Run。
  • D。使用BackgroundWorker

答案是c。然而,有人能解释一下为什么A)是不正确的吗?因为这个问题并没有说复杂算法是受CPU限制的。如果它是CPU限制,那么我们将不得不使用任务(一个原因我不太明白,虽然我知道任务确实有助于导致当前线程被挂起,直到它们完成)。此外,请解释如何决定何时使用async/await,以及何时使用Tasks。

Use async await or task?

你是做什么的?

。使用异步/等待。

B。同步运行代码

C。使用Task.Run。

D。使用BackgroundWorker

c# 5.0中的async/await特性是为了使异步代码"更容易"而实现的。如编写同步代码。如果你看一下WinAPI,你会发现几乎所有的异步端点都公开了一个完全异步的api,这意味着没有线程。进一步观察,您将注意到这些相同的端点正在执行I/O绑定操作。

假设你的算法是CPU约束的,并且是以一种允许跨多个处理器有效计算的方式编写的(例如,你的算法没有任何需要同步的共享状态),你可以利用。net 4.0中引入的任务并行库。TPL提供了对ThreadPool的抽象,它反过来试图在多处理器环境中均匀地卸载工作。

await关键字可以在任何可等待对象上使用,这意味着该对象实现了GetAwaiter方法。在使用可等待对象时,您可能希望使用await,并希望在该可等待对象完成其工作后恢复执行。Task实现了可等待模式,用于描述将在将来完成的工作单元。你可以使用Task.Runawait,当你想卸载工作线程上的一个工作单元,你想返回控制到调用方法,直到工作完成

另一种跨多个处理器调度CPU绑定工作的方法是使用Parallel类,它公开了Parallel.ForParallel.ForEach

在一个旁注,BackgroundWorker也可以用来卸载工作的后台线程,如果这是什么人问的问题后。自从。net 4.0发布以来,建议使用TPL。

总之,使用任务并行库是将工作卸载给后台线程的推荐方法。您可以将它们与Parallel库结合使用,以最大化您的算法的并行性。在这样做之后,测试你的代码,以确保使用多线程的开销不会超过同步运行算法所花费的时间。

编辑

正如Stephan在评论中提到的,你可以结合Parallel.ForEachTask.Run来卸载背景线程中的并行循环:

var task = Task.Run(() => Parallel.ForEach(.. //Loop here));

我认为在没有其他信息的情况下,"计算"意味着CPU绑定算法。如果算法是IO绑定的,async/await不仅是可以接受的,而且是正确的答案。

我相信这个问题假设您有一个同步编程的算法。问题提到这是一个"计算",这模糊地暗示了它是cpu限制的。它还非常模糊地暗示算法是同步编写的。例句:

public int CalculateStuff() {
     ....
}

我要考虑的是创建一个异步的方法:

public async Task<int> CalculateStuffAsync() {
      return await Task.Run(() => CalculateStuff());
}

然后在你的用户界面:

LoadingIndicator.IsEnabled = true;
ResultTextBox.Text = await CalculateStuffAsync();
LoadingIndicator.IsEnabled = false;

因此,正确的答案可能是A和c。无论如何,这个问题太模糊了,无法得出任何可靠的结论。