非异步执行路径能否以“异步"方式返回同步结果?方法 [英] Can non-asynchronous execution paths return synchronous results in an "async" method

查看:27
本文介绍了非异步执行路径能否以“异步"方式返回同步结果?方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下方法:

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.>

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

<块引用>

执行以下操作会有所改进吗?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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆