我在C#中获取了async / await关键字,以及它们如何促进异步编程 - 允许在其他地方使用该线程,而某些I / O绑定任务如db调用正在进行中。
我已经多次读过async / await用于I / O绑定任务,而不是CPU绑定任务。 CPU绑定任务应该在单独的后台线程上执行。在这些videos中多次提到过。一切都好。
但是,当使用Task.Run
在新线程上启动长时间运行的CPU绑定工作时,您必须在某个时刻await
。那么我们是否也在使用async / await来处理CPU绑定的任务呢?见下面的例子。
public async Task SomeMethodAsync()
{
int result = await Task.Run(() =>
{
// Do lots of CPU bound calculations...
return result;
}
// Then do something with the result.
}
答案 0 :(得分:8)
async/await
是进行异步编程的当代且最简单的方法; Task
是否需要一个帖子。
例如,它非常适合WinForms或WPF,因为主线程可以await
一个子任务来计算Piggy小姐在一年中吃午餐的次数(一个相当长且复杂的CPU绑定操作让& #39; s说)并且当完成执行紧接下面的下一行时。与传统的异步回调不同,它使您的代码非常直观; WaitOne
或其他机制以及与之相关的杂耍行为。
MSDN:
通过使用异步编程,您可以避免性能瓶颈并提高应用程序的整体响应能力。但是,用于编写异步应用程序的传统技术可能复杂,这使得它们难以编写,调试和维护。
Visual Studio 2012引入了一种简化的方法,即异步编程,它利用.NET Framework 4.5和Windows运行时中的异步支持。 编译器执行开发人员过去的艰巨工作,,并且您的应用程序保留了类似于同步代码的逻辑结构。 More...
OP:
我已多次读过async / await用于I / O绑定任务
不正确的。 async/await
是异步编程的简写,编译器可以完成更多的工作。它不仅适用于I / O绑定任务。 CPU绑定任务通常使用线程池线程。
CPU绑定任务应该在单独的后台线程上执行。
是的......但这并不代表你await
Task
await
。与I / O绑定任务不同的CPU绑定任务需要一个线程来运行,并且根据定义工作线程,因此将从可用线程池中获取一个。
但是,当使用Task.Run在新线程上启动长时间运行的CPU绑定工作时,您必须在某个时刻等待它
您不必Task
await
,此类任务将被称为“即发即弃”。 Task
实际上并没有启动它,任务是"热"。但是,如果不等待,您将面临应用程序退出时未完成任务的风险。例如一个控制台应用程序触发Task
而不等待它然后退出。
因此,我们是否也在使用async / await来处理CPU绑定任务?
没错,你可以将它用于任何display:flex
,无论它是否受I / O限制。
答案 1 :(得分:1)
如果您await
某事,您承诺将从等待的操作中获得结果。通常,您期望等待的操作是异步\后台操作,将来会执行。同时,您可以继续您的工作,这可以独立于该操作的结果完成。
async/await
确实是编译器帮助归档它。 await
将控件返回给调用者并异步处理等待操作。可以用不同的方式提供异步性。
I / O操作将在内核空间中异步处理,因此您无需为I / O操作创建其他线程。
在系统API调用之后,请求现在位于内核空间中 它通往操作系统的网络子系统(例如/ net中的网络) Linux内核)。操作系统将处理网络请求 异步。细节可能会有所不同,具体取决于使用的操作系统( 设备驱动程序调用可能被调度为发送回的信号 可以进行运行时或设备驱动程序调用,然后发送信号 返回),但最终运行时将通知网络 请求正在进行中。这时,为设备驱动程序工作 将被安排,正在进行或已经完成( 请求已经“通过电线”) - 但因为这就是全部 异步发生,设备驱动程序能够立即执行 处理其他事情!
另一方面,对于CPU操作,你必须指示CPU以异步方式执行这些操作,通常这是从不同的线程完成的(你有Task.Run
的原因。)
CPU绑定的异步代码与I / O绑定的异步代码略有不同。 因为工作是在CPU上完成的,所以无法绕过 专门用于计算的线程。使用async和await 为您提供了一种与后台线程进行交互的简洁方法 保持异步方法的调用者响应。请注意,这样做 不为共享数据提供任何保护。如果您使用共享 数据,您仍然需要应用适当的同步 策略。
重点是,在这两种情况下,你必须await
才能等待履行承诺。