在异步方法中省略 async 和 await [英] eliding async and await in async methods

查看:30
本文介绍了在异步方法中省略 async 和 await的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个简单的问题;阅读这篇文章:http://blog.stephencleary.com/2016/12/eliding-async-await.html

a quick question; reading this article: http://blog.stephencleary.com/2016/12/eliding-async-await.html

它通常告诉我,使用 async/await.已经在这样做了.但是,他还说在代理任务时不必使用异步部分.

it generally tells me, use async/await. Allready doing that. However, he is also saying that you don't have to use the async part when you are proxying the task.

// 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?这不是不太方便吗,这甚至有意义吗?

why should be not use async/await when passing through? Isn't that less convenient, and does this even make sense?

有什么想法吗?

推荐答案

为什么在通过时不应该使用 async/await?

why should be not use async/await when passing through?

因为在您键入 await 的那一刻,编译器会添加 的实现胶水,对您来说绝对没有任何作用 - 调用者已经可以只是等待代理的任务.

because the moment you type await, the compiler adds a ton of implementation glue that does absolutely nothing for you - the caller can already just await the proxied task.

如果我添加类似于您的 PassthroughAsync 的内容,但使用 async/await:

If I add something like your PassthroughAsync, but with the async/await:

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

然后我们可以通过编译和反编译IL来看到巨大但完全冗余的代码:

then we can see the huge but completely redundant code by compiling it and decompiling the 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 passthru 编译成的内容:

Now contrast to what the non-async passthru compiles to:

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

除了绕过大量的 struct 初始化和方法调用之外,如果它实际上是异步的,则可能在堆上装箱"(它不会在已经完成的情况下装箱")-同步情况),这个 PassthroughAsync 也将是 JIT 内联的一个很好的候选者,所以在实际 CPU 操作码中,PassthroughAsync 可能不会甚至存在.

In addition to bypassing a huge amount of struct initialization and method calls, a possible "box" onto the heap if it is actually async (it doesn't "box" in the already-completed-synchronously case), this PassthroughAsync will also be a great candidate for JIT-inlining, so in the actual CPU opcodes, PassthroughAsync will probably not even exist.

这篇关于在异步方法中省略 async 和 await的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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