非异步执行路径能否以“异步”方法返回同步结果

时间:2021-05-07 15:02:43

标签: c# asynchronous async-await task

考虑以下方法:

public async Task<string> GetNameOrDefaultAsync(string name)
{
    if (name.IsNullOrDefault())
    {
        return await GetDefaultAsync();
    }

    return name;
}

当提供 name 时,方法执行中不会发生等待,但该方法将正确编译。

但是,此方法会产生如下所示的构建警告:

public async Task<string> GetDefaultAsync()
{
    return "foobar";
}

[CS1998] This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

为什么 GetNameOrDefaultAsync 可以在不等待的情况下返回,并且不会导致编译器警告,但 GetDefaultAsync 必须等待才能编译?

执行以下操作是否会有所改进?:

public async Task<string> GetNameOrDefaultAsync(string name)
{
    if (name.IsNullOrDefault())
    {
        return await GetDefaultAsync();
    }

    return await Task.FromResult(name);
}

在这里,我们将没有不await 某些内容的执行路径。

1 个答案:

答案 0 :(得分:5)

<块引用>

为什么 GetNameOrDefault 无需等待就可以返回,并且不会导致编译器警告

因为存在使用 await 的执行路径,并且为了能够使用 await,该方法需要为 async

另一方面,如果没有使用 await 的路径,则 async 关键字显然是多余的,因此是警告。

<块引用>

执行以下操作会有所改进吗? return await Task.FromResult(name);

不,Task.FromResult 只是将 name 包装在处于完成状态的 Task 对象中,这意味着 await 会立即再次解开它。

这不必要地分配了一个 Task,并且没有任何效果。


顺便说一句,如果 name.IsNullOrDefault() 几乎总是 false,即使用 await 是例外而不是规则,您可以通过使用 ValueTask 来减少分配:{ {3}}