等待或Task.FromResult [英] Await or Task.FromResult

查看:136
本文介绍了等待或Task.FromResult的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一项服务可以说,

public interface ISomeService
{
    Task<bool> DoSomeExpensiveCheckAsync(string parameter);
}

我有此类可以使用该服务。它只需要做一些简单的空检查,然后返回服务响应即可。

And I have this class to consume the service. It just needs to do some simple null checks and then return the service response back.

public class SomeServiceConsumer
{
    private readonly ISomeService _serviceClient;

    public SomeServiceConsumer(ISomeService serviceClient)
    {
        _serviceClient = serviceClient;
    }

    public async Task<bool> DoSomething1Async(string someParameter)
    {
        if (string.IsNullOrWhiteSpace(someParameter))
        {
            return false;
        }
        return await _serviceClient.DoSomeExpensiveCheckAsync(someParameter);
    }

    //No async or await keywords   
    public Task<bool> DoSomething2Async(string someParameter)
    {
        if (string.IsNullOrWhiteSpace(someParameter))
        {
            return Task.FromResult(false);
        }
        return _serviceClient.DoSomeExpensiveCheckAsync(someParameter);
    }
}

我应该做 DoSomething1Async DoSomething2Async

根据这个答案,我不应该用不必要的 await 换行,但是我必须使用 Task .FromResult(false)用于短路,如 DoSomething2Async

According to this answer, I should not wrap with an unnecessary await but then I have to use Task.FromResult(false) for shortcircuiting as in DoSomething2Async

,但根据此答案有时会出现 try / catch 使用语句,实际上我应该在返回之前先等待

But according to this answer there are cases with try/catch and using statements where I actually should await before returning.

我纠正了然后说,


  1. 如果我必须使用 try / catch 使用,那么我应该等待

否则,如果您仅打算返回,请不要等待。并使用 Task.FromResult 进行短路

Otherwise do not await if you are only going to return. And use Task.FromResult for short circuiting

我喜欢 DoSomething1Async 更多,并且如果有人说没关系,想在任何地方都可以这样做:)。

I like DoSomething1Async more, and want to do that everywhere if someone says it doesnt matter :).

推荐答案

如果您担心它,请缓存 Task

If you're worried about it, cache the Task:

static readonly Task<bool> falseTask = Task.FromResult(false);

async 关键字还将异常包裹起来返回的 Task 以及正确的堆栈跟踪。这是权衡的行为,是行为的安全性。

The async keyword also wraps exceptions up in the returned Task, along with a proper stack trace. It's a tradeoff, safety of behavior for perf.

让我们看一下每个场景都不同的不同场景:

Lets look at the difference scenarios where each would be different:

async Task UseSomething1Async(string someParameter)
{
    // if IsNullOrWhiteSpace throws an exception, it will be wrapped in
    // the task and not thrown here.
    Task t1 = DoSomething1Async(someParameter);

    // rather, it'll get thrown here. this is best practice,
    // it's what users of Task-returning methods expect.
    await t1;

    // if IsNullOrWhiteSpace throws an exception, it will
    // be thrown here. users will not expect this.
    Task t2 = DoSomething2Async(someParameter);

    // this would never have been reached.
    await t2;
}

此处仅说明了这一点- IsNullOrWhiteSpace 实际上不会因任何原因引发任何异常。

Just illustrating the point here -- IsNullOrWhiteSpace does not actually throw any exceptions for any reason.

就堆栈跟踪而言,异步堆栈跟踪取决于您等待。没有 await 表示该方法将从堆栈跟踪中消失。

As far as stack traces go, async stack traces are determined by where you await. No await means the method will disappear from the stack trace.

DoSomeExpensiveCheckAsync 引发异常。在 DoSomething1Async 的情况下,堆栈跟踪看起来像 caller->。 DoSomething1Async-> DoSomeExpensiveCheckAsync

Say DoSomeExpensiveCheckAsync throws an exception. In the case of DoSomething1Async, the stack trace will look like caller -> DoSomething1Async -> DoSomeExpensiveCheckAsync.

对于 DoSomething2Async ,堆栈跟踪看起来像 caller-> DoSomeExpensiveCheckAsync

In the case of DoSomething2Async, the stack trace would look like caller -> DoSomeExpensiveCheckAsync. Depending on the complexity of your code, this can make things difficult to debug.

实际上,我一般只会直接返回 Task code>如果我不知道会在其之前引发任何异常,并且方法名仅仅是一个重载,则转发给另一个重载。此规则总是有例外,肯定有一些您想最大化性能的地方。只需仔细选择,就可以意识到您可能会使您和您的用户的生活变得更加艰难。

In practice, I will generally only directly return a Task if I knew no exceptions would be thrown prior to it, and if the method name was merely an overload forwarding to another overload. There are always exceptions to this rule, there are bound to be places you want to maximize performance. Just pick and choose carefully, realize you might be making the life of you and your user harder.

这篇关于等待或Task.FromResult的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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