为什么要使用C#async/await来执行CPU限制的任务

为什么要使用C#async/await来执行CPU限制的任务,c#,multithreading,asynchronous,async-await,task-parallel-library,C#,Multithreading,Asynchronous,Async Await,Task Parallel Library,我了解了C#中async/await关键字的诀窍,以及它们如何促进异步编程——允许线程在其他地方使用,同时执行一些I/O绑定任务,如db调用 我已经读过很多次,async/await用于I/O绑定的任务,而不是CPU绑定的任务。CPU绑定的任务应该在单独的后台线程上执行。在这些文章中多次提到。好的 但是,当使用Task.Run在新线程上启动长时间运行的CPU绑定工作时,您必须在某个时间点等待它。那么,我们在这里不是也使用async/await来执行CPU限制的任务吗?见下面的例子 public

我了解了C#中async/await关键字的诀窍,以及它们如何促进异步编程——允许线程在其他地方使用,同时执行一些I/O绑定任务,如db调用

我已经读过很多次,async/await用于I/O绑定的任务,而不是CPU绑定的任务。CPU绑定的任务应该在单独的后台线程上执行。在这些文章中多次提到。好的

但是,当使用
Task.Run
在新线程上启动长时间运行的CPU绑定工作时,您必须在某个时间点等待它。那么,我们在这里不是也使用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.
}

async/await
是进行异步编程的当代最简单的方法,无论作业是否受I/O限制;
任务
是否需要线程

例如,这对于WinForms或WPF来说是非常好的,因为主线程可以
等待子任务来计算Piggy小姐一年中吃午饭的次数(比方说,这是一个相当长且复杂的CPU限制操作),并且在完成时执行下面的下一行。它使您的代码非常直观,不像经典的异步回调
WaitOne
s或其他机制以及与之配套的杂耍动作

MSDN:

通过使用异步编程,您可以避免性能瓶颈并增强应用程序的整体响应能力。然而,用于编写异步应用程序的传统技术可能非常复杂,难以编写、调试和维护

Visual Studio 2012引入了一种简化的方法,即异步编程,它利用了.NET Framework 4.5和Windows运行时中的异步支持编译器完成了开发人员过去所做的困难工作,,而您的应用程序保留了类似同步代码的逻辑结构

作品:

我已经读过很多次,async/await用于I/O绑定的任务

不对
async/await
是异步编程的简写,在异步编程中,编译器会做更多的工作。它不仅仅适用于I/O绑定的任务。CPU绑定的任务通常使用线程池线程

CPU绑定的任务应该在单独的后台线程上执行

是的……但这并不意味着你不能等待
任务
。CPU绑定的任务与I/O绑定的任务不同需要一个线程来操作,根据定义,工作线程
,因此将从可用的线程池中获取一个

然而,当使用Task.Run在新线程上启动长时间运行的CPU绑定工作时,您必须在某个时刻等待它

你不必等待一个
任务,这类任务被称为“开火遗忘”。等待
实际上也不会启动它,任务是“热的”。但是,如果不等待,则可能在应用程序退出时任务无法完成。e、 g.控制台应用程序启动
任务
,不等待,然后退出

那么,我们在这里不是也使用async/await来执行CPU限制的任务吗

没错,您可以将它用于任何
任务
,无论它是否为I/O绑定

更多

如果你等待
某件事,你有一个承诺,那就是你将从等待的操作中得到结果。通常,您希望等待的操作是异步\后台操作,该操作将在将来执行。同时,您可以继续您的工作,这可以独立于该操作的结果来完成

async/await
确实可以帮助编译器归档它
await
将控件返回给调用方,并异步处理等待的操作。异步可以以不同的方式提供

一旦I/O操作进入内核空间,它们将被异步处理,所以您不需要为I/O操作创建额外的线程

在系统API调用之后,请求现在位于内核空间,使 它通向操作系统的网络子系统(如 Linux内核)。在这里,操作系统将处理网络请求 异步的。根据使用的操作系统的不同,详细信息可能会有所不同 设备驱动程序呼叫可以被安排为发送回设备的信号 运行时或设备驱动程序调用,然后发送信号 返回),但最终运行时将被告知 请求正在进行中。此时,设备驱动程序的工作已完成 将被安排、正在进行或已经完成 请求已经“通过连线”发出了-但因为这就是全部 异步发生时,设备驱动程序能够立即 处理其他事情

另一方面,对于CPU操作,您必须以某种方式指示CPU以异步方式进行操作,通常这是从不同的线程完成的(这就是您有
Task.Run
)的原因)

CPU绑定异步代码与I/O绑定异步代码略有不同。 因为这项工作是在CPU上完成的,所以无法四处走动 将线程专用于计算。异步和等待的使用 为您提供了一种与后台线程和 使异步方法的调用方保持响应。请注意,这是正确的 不为共享数据提供任何保护。如果您使用的是共享 数据,您仍然需要应用适当的同步 战略


关键是,在这两种情况下,您都必须等待,以等待承诺的实现。

关键是,在操作系统的核心中,I/O操作是异步的,当您调用内核时,它无论如何都是异步的,但对于CPU操作,您需要利用线程来指示CPU异步执行操作…您不必执行任务。运行到在新线程上执行。如果你等待并且