【发布时间】:2018-08-02 09:04:26
【问题描述】:
我正在了解 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.
}
【问题讨论】:
-
关键是 I/O 操作在操作系统的核心是异步的,然后当你调用内核时它无论如何都会异步执行,但是对于 CPU 操作,你需要利用线程来指示 CPU 执行它异步...
-
您不必在新线程上执行 Task.Run。如果您 await 和
ConfigureAwait(false)您将(很可能)在不同的线程池线程上运行该代码。而且,您是否暗示您不等待 I/O 操作?除非您真的确定只需要“即发即弃”,否则您应该始终等待。 -
“我读过很多次 async/await 是针对 I/O 密集型任务,而不是 CPU 密集型任务。” 需要引用。我怀疑它是这样写的,你可能会误解这个信息。
-
这里有解释docs.microsoft.com/en-us/dotnet/standard/async-in-depth。我认为令人困惑的是,对于 CPU 密集型任务,您需要从另一个线程执行它,但您仍然使用 await...
-
对于桌面 GUI 应用程序,CPU 绑定操作可能会阻塞事件处理程序中的 UI,因此通常最好使处理程序异步并将底层操作包装在 Task.Run 中并等待。使用 ASP.NET,请求已经有一个专用线程。等待 CPU 绑定操作的 Task.Run 只会让您有两个线程在做同样的工作。即使现有请求正在处理,无论是否异步,下一个请求仍会从池中选择另一个线程。对于 I/O 绑定请求,您总是希望利用可用的异步操作,并且不会创建额外的线程。
标签: c# multithreading asynchronous async-await task-parallel-library