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。
c# 5.0中的你是做什么的?
。使用异步/等待。
B。同步运行代码
C。使用Task.Run。
D。使用BackgroundWorker
async/await
特性是为了使异步代码"更容易"而实现的。如编写同步代码。如果你看一下WinAPI,你会发现几乎所有的异步端点都公开了一个完全异步的api,这意味着没有线程。进一步观察,您将注意到这些相同的端点正在执行I/O绑定操作。假设你的算法是CPU约束的,并且是以一种允许跨多个处理器有效计算的方式编写的(例如,你的算法没有任何需要同步的共享状态),你可以利用。net 4.0中引入的任务并行库。TPL提供了对ThreadPool的抽象,它反过来试图在多处理器环境中均匀地卸载工作。
await
关键字可以在任何可等待对象上使用,这意味着该对象实现了GetAwaiter
方法。在使用可等待对象时,您可能希望使用await
,并希望在该可等待对象完成其工作后恢复执行。Task
实现了可等待模式,用于描述将在将来完成的工作单元。你可以使用Task.Run
和await
,当你想卸载工作线程上的一个工作单元,你想返回控制到调用方法,直到工作完成。
另一种跨多个处理器调度CPU绑定工作的方法是使用Parallel
类,它公开了Parallel.For
和Parallel.ForEach
。
BackgroundWorker
也可以用来卸载工作的后台线程,如果这是什么人问的问题后。自从。net 4.0发布以来,建议使用TPL。
总之,使用任务并行库是将工作卸载给后台线程的推荐方法。您可以将它们与Parallel
库结合使用,以最大化您的算法的并行性。在这样做之后,测试你的代码,以确保使用多线程的开销不会超过同步运行算法所花费的时间。
编辑
正如Stephan在评论中提到的,你可以结合Parallel.ForEach
和Task.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。无论如何,这个问题太模糊了,无法得出任何可靠的结论。