我想了解async / await。我知道你不应该等待一个受CPU限制的方法,但是为了帮助我理解我很好奇如果你这样做会发生什么。考虑:
Public Async Function DoSomeTasks()
Await LongRunningCPUBoundMethod1()
LongRunningCPUBoundMethod2()
End Function
Public Async Function LongRunningCPUBoundMethod1() As Task
' Do stuff synchronously
End Function
Public Sub LongRunningCPUBoundMethod2()
' Do stuff synchronously
End Sub
Task Scheduler如何处理CPU资源?这些方法将以什么顺序执行? LongRunningCPUBoundMethod1或LongRunningCPUBoundMethod2会先执行吗?
答案 0 :(得分:5)
这里需要记住的是Async
/ Await
代码不一定是多线程的。您可以通过等待启动单独线程的项来使用它们来帮助处理多线程代码,但它们真正做的是允许您在同一个线程中有效地分解多个任务。
这不是没有一些开销;在异步任务之间切换会产生成本。当你等待cpu绑定任务时,你已经将这个成本添加到已经cpu密集的工作中,因此使事情变得更糟而不是更好。但是,如果将此与在单独线程中启动cpu-heavy任务的代码相结合,然后使用WaitHandle或Task将结果发回,则可能再次正常(取决于如何您正在等待相关可用内核数量的许多项目,因为现在您正在利用CPU中的多个内核。
此外,让我们在.Net WinForms的背景下看一下。重要的是要记住,你永远不想在主UI线程上做大量的CPU工作。实际上,阻塞超过几毫秒的任何都是有问题的。如果该线程忙,Windows消息泵不运行,您无法响应事件,并且您的用户界面变得无法响应。
要在此上下文中理解Await
,请将其视为将方法分为两部分(或更多,如果有多个Await
)。包含Await
行的所有内容都会立即运行,并且await之后的所有内容都会被编译器隐藏在一个新的回调方法(称为 continuation )中,该方法将使用相同的上下文(包括原始方法的局部变量)以及Await
完成后的同一个线程。
有了这些信息,应该很清楚,如果你直接Await
一个cpu绑定方法,你仍然在UI线程上立即做这项工作,你的用户界面仍然有问题。但是,您可以通过在其自己的线程中启动cpu-bound方法来解决此问题。 Await
与Task
一起使用,无需编写大量新代码即可轻松完成。当然,它比旧的DoEvents()
技术要好得多。
答案 1 :(得分:1)
执行顺序。
1。)LongRunningCPUBoundMethod1()
2。)LongRunningCPUBoundMethod2()
下面是你如何搞乱程序流程和执行
var task = LongRunningCPUBoundMethod1();
LongRunningCPUBoundMethod2();
var result = await task;
// now result contains what was returned by LongRunningCPUBoundMethod1()
抱歉,我不知道await / async如何影响CPU资源。