在异步方法中省略 async 和 await

11 浏览
0 Comments

在异步方法中省略 async 和 await

一个快速的问题;阅读这篇文章:http://blog.stephencleary.com/2016/12/eliding-async-await.html\n文章主要告诉我要使用async/await。我已经在使用了。然而,他还说当你在代理任务时不需要使用async部分。\n

// 简单的透传到下一层:省略。
Task PassthroughAsync(int x) => _service.DoSomethingPrettyAsync(x);
// 方法的简单重载:省略。
async Task DoSomethingPrettyAsync(CancellationToken cancellationToken)
{
    ... // 核心实现,使用await。
}

\n为什么在透传时不使用async/await呢?这难道不是更方便吗?这有意义吗?\n任何人有想法吗?

0
0 Comments

为什么在传递时不应使用async/await?

因为只要你键入await,编译器就会添加大量的实现代码,而这些代码对你来说完全无用——调用者已经可以直接等待代理任务。

如果我添加类似于你的PassthroughAsync的代码,但带有async/await:

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

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

[AsyncStateMachine(typeof(d__1))]

private Task AwaitedAsync(int x)

{

d__1 d__ = default(d__1);

d__.<>4__this = this;

d__.x = x;

d__.<>t__builder = AsyncTaskMethodBuilder.Create();

d__.<>1__state = -1;

AsyncTaskMethodBuilder <>t__builder = d__.<>t__builder;

<>t__builder.Start(ref d__);

return d__.<>t__builder.Task;

}

[StructLayout(LayoutKind.Auto)]

[CompilerGenerated]

private struct d__1 : IAsyncStateMachine

{

public int <>1__state;

public AsyncTaskMethodBuilder <>t__builder;

public C <>4__this;

public int x;

private TaskAwaiter <>u__1;

private void MoveNext()

{

int num = <>1__state;

C c = <>4__this;

string result;

try

{

TaskAwaiter 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);

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编译为的代码进行对比:

private Task PassthroughAsync(int x)

{

return DoSomethingPrettyAsync(x);

}

除了绕过大量的结构初始化和方法调用之外,如果实际上是异步的(在已同步完成的情况下不会“box”到堆上),这个PassthroughAsync还是一个很好的JIT内联候选对象,所以在实际的CPU操作码中,PassthroughAsync可能甚至不存在。

0