簡體   English   中英

在異步方法中消除異步並等待

[英]eliding async and await in async methods

一個簡短的問題; 閱讀本文: http : //blog.stephencleary.com/2016/12/eliding-async-await.html

它通常告訴我,請使用async / await。 已經准備好了。 但是,他也說代理任務時不必使用異步部分。

// Simple passthrough to next layer: elide.
Task<string> PassthroughAsync(int x) => _service.DoSomethingPrettyAsync(x);

// Simple overloads for a method: elide.
async Task<string> DoSomethingPrettyAsync(CancellationToken cancellationToken)
{
    ... // Core implementation, using await.
}

為什么在通過時不應該使用async / await? 難道不是那么方便,這是否有意義?

有任何想法嗎?

為什么在通過時不應該使用async / await?

因為在您鍵入await的那一刻,編譯器會添加大量實現膠水, 對您完全沒有任何作用 -調用者已經可以剛剛等待代理任務。

如果我添加類似PassthroughAsync ,但使用async / await

async Task<string> AwaitedAsync(int x) => await DoSomethingPrettyAsync(x);

然后我們可以通過編譯並反編譯IL來查看龐大但完全冗余的代碼:

[AsyncStateMachine(typeof(<AwaitedAsync>d__1))]
private Task<string> AwaitedAsync(int x)
{
    <AwaitedAsync>d__1 <AwaitedAsync>d__ = default(<AwaitedAsync>d__1);
    <AwaitedAsync>d__.<>4__this = this;
    <AwaitedAsync>d__.x = x;
    <AwaitedAsync>d__.<>t__builder = AsyncTaskMethodBuilder<string>.Create();
    <AwaitedAsync>d__.<>1__state = -1;
    AsyncTaskMethodBuilder<string> <>t__builder = <AwaitedAsync>d__.<>t__builder;
    <>t__builder.Start(ref <AwaitedAsync>d__);
    return <AwaitedAsync>d__.<>t__builder.Task;
}
[StructLayout(LayoutKind.Auto)]
[CompilerGenerated]
private struct <AwaitedAsync>d__1 : IAsyncStateMachine
{
    public int <>1__state;

    public AsyncTaskMethodBuilder<string> <>t__builder;

    public C <>4__this;

    public int x;

    private TaskAwaiter<string> <>u__1;

    private void MoveNext()
    {
        int num = <>1__state;
        C c = <>4__this;
        string result;
        try
        {
            TaskAwaiter<string> awaiter;
            if (num != 0)
            {
                awaiter = c.DoSomethingPrettyAsync(x).GetAwaiter();
                if (!awaiter.IsCompleted)
                {
                    num = (<>1__state = 0);
                    <>u__1 = awaiter;
                    <>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
                    return;
                }
            }
            else
            {
                awaiter = <>u__1;
                <>u__1 = default(TaskAwaiter<string>);
                num = (<>1__state = -1);
            }
            result = awaiter.GetResult();
        }
        catch (Exception exception)
        {
            <>1__state = -2;
            <>t__builder.SetException(exception);
            return;
        }
        <>1__state = -2;
        <>t__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)
    {
        <>t__builder.SetStateMachine(stateMachine);
    }

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

現在對比一下非async傳遞編譯為:

private Task<string> PassthroughAsync(int x)
{
    return DoSomethingPrettyAsync(x);
}

除了繞過大量的struct初始化和方法調用之外,如果堆實際上是異步的(在已經完成同步的情況下不是“箱子”),則可能在堆上出現“箱子”,該PassthroughAsync也將是JIT內聯的理想之選,因此在實際的CPU操作碼中PassthroughAsync可能甚至不存在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM