将常规匿名函数和异步匿名函数传递给 Task.Run 以进行异步工作的区别

Difference between passing a regular and async anonymous function to Task.Run for asynchronous work

有什么区别

ResultType result = await Task.Run(() => GetResultAsync())

ResultType result = await Task.Run(async() => await GetResultAsync())

我推测前者会触发并忘记 GetResultAsync(),因为它没有等待,但它是如何得到结果的呢?我很惊讶前者Task.Run的return类型是Task<ResultType>而不是Task<Task<ResultType>>

在您开始的 'Task.Run' 的第一行,立即 return 是 'GetResultAsync' 的结果。然而,该结果是一个可以等待的任务(由您的'await')。 所以,你实际上 'await' 'GetResultAsync' 方法。

在第二行中,您启动了一个不会立即 return 的任务,而是等到 'GetResultAsync'(异步调用)完成。您的任务 return 类型是 'ResultType'。 所以你 'await' 你自己的任务,在等待 'GetResultAsync' 方法后,它只会 return。

最后,他们都完成了相同的结果,但方式略有不同。

从结果的角度来看,两者都是一样的。在这两种情况下,都使用了重载 Task.Run<TResult>(Func<Task<TResult>> function) 来在内部解包任务 - 这就是结果为 Task<ResultType> 的原因。它们之间的差异相当于

之间的差异
    static Task<T> Compute()
    {
        return GetAsyncResult();
    }

    static async Task<T> Compute()
    {
        return await GetAsyncResult();
    }

在第一种情况下,promise 只是传递回调用者,而在第二种情况下,状态机由编译器围绕 Compute 方法构建。