正在等待任务.运行(NonAsyncMethod())会更好

本文关键字:更好 在等待 NonAsyncMethod 运行 任务 | 更新日期: 2023-09-27 18:24:59

让我们说,我有一个这样的调用:

await Task.Run(async() => SomeLongRunningNonAsyncMethod());

我的理解是,当调用SomeLongRunningNonAsyncMethod()时,该调用直到遇到等待时才会返回。但是SomeLongRunningNonAsyncMethod()中没有等待。

那么,这与直接SomeLongRunningNonAsyncMethod()调用相同吗?

正在等待任务.运行(NonAsyncMethod())会更好

我的理解是,当调用SomeLongRunningNonAsyncMethod()时,该调用直到遇到等待时才会返回。但在SomeLongRunningNonAsyncMethod()中没有等待。

您需要区分传递给Task.RundelegateTask.Run 的实际执行

前者将在ThreadPool线程内同步执行。您不需要使用async关键字,因为您不等待给定委托内的任何异步操作。

Task.Run开始执行时,后者将达到其await,并将控制权交还给调用方法,直到委托完成执行。

那么,这与直接SomeLongRunningNonAsyncMethod()调用相同吗?

没有。直接调用将在当前运行的线程上同步执行。您的代码在ThreadPool线程上同步执行委托,同时调用Task.Run的线程以非阻塞方式等待Task的完成。

您的代码实际上应该是:

await Task.Run(SomeLongRunningNonAsyncMethod);

您的理解确实存在缺陷。

当代码执行到达await Task.Run时,它将首先像往常一样执行Task.Run(这将使方法在线程池上排队),然后立即返回。当Task.Run内部的方法完成时,将在await之后继续执行。

这是否有用在很大程度上取决于你的背景。例如,如果您从WinForms/WPF应用程序中的事件处理程序调用此函数,这确实是避免在执行某些后台工作时阻塞UI线程的好方法。如果您在web应用程序中这样做,那么您只是无端地导致线程切换和线程池线程。

如果您在Task.Run中执行I/O,而不是CPU工作,则需要找到一个异步API来执行相同的I/O工作-这将为您保存在I/O请求完成时无论如何都会阻塞的线程。

一旦返回对Task.Run的调用,await关键字将导致控制权返回到调用方法。该调用返回"立即"(它只会使用当前任务调度程序来调度操作,而不是等待它完成)。一旦任务完成,await行后面的代码将继续执行。