繁体   English   中英

使用异步等待或任务?

[英]Use async await or task?

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

  • A.使用async / await。
  • B.同步运行代码。
  • C.使用Task.Run。
  • D.使用BackgroundWorker。

答案是C.但是,有人可以解释为什么A)不正确吗? 因为问题并不是说复杂的算法是CPU绑定的。 如果它是CPU绑定的,那么我们将不得不使用任务(一种我不太了解的推理,但我知道任务确实有助于导致当前线程被挂起直到它们完成)。 另外,请解释如何决定何时使用async / await,并使用Tasks。

你是做什么?

A.使用async / await。

B.同步运行代码。

C.使用Task.Run。

D.使用BackgroundWorker。

实现了C#5.0中的async/await功能,以使异步代码“像编写同步代码一样简单”。 如果你研究WinAPI,你会发现几乎所有的异步端点都暴露了一个完全异步的api,这意味着没有线程 进一步看,您会注意到那些相同的端点正在进行I / O绑定操作。

假设您的算法是CPU绑定的 ,并且以允许跨多个处理器进行有效计算的方式编写(例如,您的算法没有任何需要同步的共享状态),您可以利用中介绍的任务并行库 。 NET 4.0。 TPL提供了对ThreadPool的抽象,而ThreadPool又试图在多处理器环境中均匀地卸载工作。

await关键字可用于任何等待对象,这意味着该对象实现了GetAwaiter方法。 当你正在使用await时,你会希望使用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.无论如何,这个问题太模糊,无法得出任何可靠的结论。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM