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

Ben*_*eds 2 c# asynchronous task async-await

考虑以下方法:

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

    return name;
}
Run Code Online (Sandbox Code Playgroud)

name被提供,不等待将发生在方法执行的,但这种方法会正确编译。

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

public async Task<string> GetDefaultAsync()
{
    return "foobar";
}
Run Code Online (Sandbox Code Playgroud)

[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);
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们将没有不做任何await事情的执行路径。

Joh*_*lay 5

为什么它GetNameOrDefault可以在不等待的情况下返回,并且不会导致编译器警告

因为确实有使用的执行路径await,并且能够使用await该方法需要是async.

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

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

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

Task不必要地分配了一个,并且什么也没有实现。


顺便说一句,如果name.IsNullOrDefault()几乎总是false,即使用await是例外而不是规则,您可以通过使用ValueTask来减少分配:为什么在 C# 中使用 Task<T> 而不是 ValueTask<T>?