从方法中提前返回时,async/await 是否会产生额外的成本?

Dir*_*oer 3 c# asynchronous async-await

与同步方法相比,从方法提前返回时 async/await 是否有额外的成本?

以这些例子为例:

public async Task<bool> TryDoSomethingAsync()
{
    if ( Is99PercentOfTheCases() )
        return false;  // does this path...

    await DoSomethingAsync();

    return true;
}

// versus 

public bool TryDoSomething()
{
    if ( Is99PercentOfTheCases() )
        return false; // ...have the same cost as this path?

    DoSomething();

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

我知道 async/await 会产生额外的成本,因此您需要注意紧密循环 - 参见即https://www.red-gate.com/simple-talk/dotnet/net-framework/the-overhead-of -asyncawait-in-net-4-5/

但是这个成本什么时候发生?

  • 是在将方法标记为异步时吗?
  • 是需要等待的时候吗?
  • 还是与任务返回类型有关?
  • 特别是:当异步方法提前返回时,性能是否仍然会发生?

最后,最好描述特定案例,但我对其背后的理论很感兴趣。

Eni*_*ity 5

TryDoSomethingAsync编译器将 get 中的代码转换为 IL 代码,或多或少相当于:

public Task<bool> TryDoSomethingAsync()
{
    TryDoSomethingAsyncStateMachine stateMachine = new TryDoSomethingAsyncStateMachine();
    stateMachine._this = this;
    stateMachine._builder = AsyncTaskMethodBuilder<bool>.Create();
    stateMachine._state = -1;
    AsyncTaskMethodBuilder<bool> _builder = stateMachine._builder;
    _builder.Start(ref stateMachine);
    return stateMachine._builder.Task;
}

private sealed class TryDoSomethingAsyncStateMachine : IAsyncStateMachine
{
    public int _state;
    public AsyncTaskMethodBuilder<bool> _builder;
    public UserQuery _this;

    private TaskAwaiter _awaiter;

    private void MoveNext()
    {
        int num = _state;
        bool result;
        try
        {
            TaskAwaiter awaiter;
            if (num == 0)
            {
                awaiter = _awaiter;
                _awaiter = default(TaskAwaiter);
                num = (_state = -1);
                goto IL_0080;
            }
            if (!_this.Is99PercentOfTheCases())
            {
                awaiter = _this.DoSomethingAsync().GetAwaiter();
                if (!awaiter.IsCompleted)
                {
                    num = (_state = 0);
                    _awaiter = awaiter;
                    TryDoSomethingAsyncStateMachine stateMachine = this;
                    _builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
                    return;
                }
                goto IL_0080;
            }
            result = false;
            goto end_IL_0007;
        IL_0080:
            awaiter.GetResult();
            result = true;
        end_IL_0007:;
        }
        catch (Exception exception)
        {
            _state = -2;
            _builder.SetException(exception);
            return;
        }
        _state = -2;
        _builder.SetResult(result);
    }

    void IAsyncStateMachine.MoveNext()
    {
        //ILSpy generated this explicit interface implementation from .override directive in MoveNext
        this.MoveNext();
    }

    [DebuggerHidden]
    private void SetStateMachine(IAsyncStateMachine stateMachine)
    {
    }

    void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
    {
        //ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
        this.SetStateMachine(stateMachine);
    }
}
Run Code Online (Sandbox Code Playgroud)

与普通异步方法相比,运行的代码要多得多。

但是,运行 的代码Is99PercentOfTheCases()仍然相当轻量。它会很快,但不如非异步方法快。