何时使用异步返回任务

本文关键字:任务 返回 异步 何时使 | 更新日期: 2023-09-27 18:34:51

当谈到处理异步/任务时,方法应该是什么样子时,我感到有些困惑。

根据我的理解,仅创建新任务的方法不需要异步,因为这会产生开销,因为它将孔包裹在新任务中。

所以这个:

async Task _doStuff()
{
    await Task.Run(()=> _stuff());
}

这样更好:

Task _doStuff()
{
    return Task.Run(()=> _stuff());
}

但是,如果有一些先决条件检查,它会变得有点复杂那么哪种方式更好呢?

async Task _doStuff()
{
    if(stuffWasDone)
        return;
    await Task.Run(()=> _stuff());
}

Task _doStuff()
{
    if(stuffWasDone)
        return Task.Run(()=> {}); // this could be a static-readonly in some helper like AsyncHelper.Empty(); as there is no FromResult for Task.
    return Task.Run(()=> _stuff());
}

何时使用异步返回任务

您不必使用 Task.Run 即可生成TaskTask就是承诺。如果不需要执行Task,请不要创建。使用 Task.Run 具有在线程池线程上调用空 lambda 的开销,您不需要它。只需返回就足够了。

如果实际上不需要Task,您也可以使用 Task.FromResult

Task DoStuffAsync()
{
    if(stuffWasDone)
    {
       return Task.FromResult(0);
    }
    return Task.Run(() => _stuff());
}

如果您不想重新生成Task,只需将其放在局部变量中:

private static Task _emptyTask = Task.FromResult(0);

至于你的第一个例子 await vs return await ,你不能说一个比另一个"更好",因为它们有不同的目的。前者将异步等待Task完成,然后再返回,而后者将向调用方返回热任务。这在异常处理方面很重要。更重要的是,如果您之后不打算使用任务的结果,则使用 await 将导致冗余生成状态机。

另一方面,在异步包装器中包装同步方法是一种不好的做法。让最终用户显式调用Task.Run,不要用异步行为欺骗他们。