何时使用异步返回任务

时间:2014-12-22 10:26:19

标签: c# .net task-parallel-library async-await

当涉及到处理异步/任务时方法应该是什么样子时,我很困惑。

根据我的理解,一个只创建一个新任务的方法不需要是异步的,因为这会产生开销,因为它在新任务中包装了这个洞。

所以这个:

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());
}

1 个答案:

答案 0 :(得分:4)

您不必使用Task.Run来生成TaskTask是一个承诺。 如果Task不需要执行,请不要创建一个。使用Task.Run有一个在线程池线程上调用空lambda的开销,你不需要它。简单回来就足够了。

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

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将导致冗余生成状态机。

另见旁注,wrapping synchronous methods in asynchronous wrappers is bad practice。让最终用户明确地调用Task.Run,不要用异步行为欺骗他们。