首页 > 解决方案 > 是否有任何理由在 Task.Run 中运行异步代码?

问题描述

我最近在 WinForm 应用程序中遇到了这段代码,我不知道是否有任何理由在等待的代码中运行async代码。Task.Run

public async Task SaveStuff()
{
    await Task.Run(() => SaveStuffAsync().ConfigureAwait(false));
    await Task.Run(() => SendToExternalApiAsync().ConfigureAwait(false));
}

private async Task SaveStuffAsync()
{
    await DbContext.SaveChangesAsync().ConfigureAwait(false);
}

private async Task SendToExternalApiAsync()
{
    // some async code that is awaited with ConfigureAwait(false);
}

如果没有Task.Run,​​这段代码不会做同样的事情吗?

public async Task SaveStuff()
{
    await SaveStuffAsync().ConfigureAwait(false);
    await SendToExternalApiAsync().ConfigureAwait(false);
}

标签: c#async-await

解决方案


如果没有Task.Run,​​这段代码不会做同样的事情吗?

如果 async 方法中的代码实际上是异步的,那并不会真正产生影响。将Task在线程池上执行,因此可能需要更多资源来执行。从调用线程的角度来看,您不会注意到差异。

但是,如果您的异步方法中的代码是(不是)同步的,您会注意到不同之处。考虑以下方法:

private async Task DoWorkNotReallyAsync()
{
    for (int i = 0; i < aVeryLargeNumber; i++)
    {
        DoSynchronousComputation();
    }
}

上面的方法有一个异步签名,但实际上是同步运行的,因此在执行时阻塞了调用线程。将调用包装在 a 中Task.Run会将执行安排到线程池。Task.Run因此,如果您想确定对 async 方法的调用不会阻塞当前线程,那么包装任务可能会很有用。

您的示例中调用的方法看起来确实是异步的,所以我看不出有理由将这些任务包装在Task.Run.


推荐阅读