非异步执行路径能否以“异步"方式返回同步结果?方法 [英] Can non-asynchronous execution paths return synchronous results in an "async" method
问题描述
考虑以下方法:
public async TaskGetNameOrDefaultAsync(字符串名称){如果 (name.IsNullOrDefault()){返回等待 GetDefaultAsync();}返回名称;}
当提供name
时,方法执行中不会发生等待,但该方法将正确编译.
但是,此方法会产生如下所示的构建警告:
public async Task获取默认异步(){返回foobar";}
[CS1998] 这种异步方法缺少await"操作符,将同步运行.考虑使用await"运算符来等待非阻塞 API 调用,或使用await Task.Run(...)"在后台线程上执行 CPU 密集型工作.
为什么 GetNameOrDefaultAsync
可以在不等待的情况下返回,并且不会导致编译器警告,但 GetDefaultAsync
必须等待才能编译?
执行以下操作是否会有所改进?:
public async TaskGetNameOrDefaultAsync(字符串名称){如果 (name.IsNullOrDefault()){返回等待 GetDefaultAsync();}返回等待 Task.FromResult(name);}
在这里,我们将没有不await
某些东西的执行路径.
为什么
GetNameOrDefault
无需等待就可以返回,并且不会导致编译器警告
因为有些执行路径确实使用了await
,并且为了能够使用await
,该方法需要是async
.>
另一方面,如果没有路径使用await
,async
关键字显然是多余的,因此警告.
执行以下操作会有所改进吗?return await Task.FromResult(name);
不,Task.FromResult
只是将 name
包装在一个 Task
对象中,该对象处于完成状态,意味着 await
立即再次打开它.
这不必要地分配了一个Task
,什么也没有实现.
顺便说一句,如果 name.IsNullOrDefault()
几乎总是 false
,即使用 await
是例外而不是规则,您可以通过使用 ValueTask
来减少分配:为什么要使用 Task<T>在 ValueTask 上在 C# 中?
Consider the following method:
public async Task<string> GetNameOrDefaultAsync(string name)
{
if (name.IsNullOrDefault())
{
return await GetDefaultAsync();
}
return name;
}
When name
is provided, no awaiting will occur in the method execution, yet this method will compile correctly.
However, this method will produce the build warning shown below:
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.
Why is it that GetNameOrDefaultAsync
can return without ever awaiting, and not result in a compiler warning, but GetDefaultAsync
must await in order to compile?
Would it be an improvement to do the following?:
public async Task<string> GetNameOrDefaultAsync(string name)
{
if (name.IsNullOrDefault())
{
return await GetDefaultAsync();
}
return await Task.FromResult(name);
}
Here we would have no execution paths that don't await
something.
Why is it that
GetNameOrDefault
can return without ever awaiting, and not result in a compiler warning
Because there are execution paths that do use await
, and to be able to use await
the method needs to be async
.
On the other hand, if there are no paths that use await
, the async
keyword is clearly superfluous, hence the warning.
Would it be an improvement to do the following?
return await Task.FromResult(name);
No, Task.FromResult
simply wraps name
in a Task
object, which is in a completed state, meaning the await
unwraps it again immediately.
This allocates a Task
unnecessarily, and achieves nothing.
As an aside, if name.IsNullOrDefault()
is almost always false
, i.e. using await
is the exception not the rule, you could reduce allocations by using ValueTask
instead: Why would one use Task<T> over ValueTask<T> in C#?
这篇关于非异步执行路径能否以“异步"方式返回同步结果?方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!