假设我有一个C#控制器,它调用一些返回Task的任意函数(例如,因为它执行数据库事务)。我应该总是使用异步和等待,还是应该只返回任务?
控制器示例:
for( i in 1:k){
for( j in 1:n){
matr1[i, 1:(n-j+1)] <- matr1[i, 1:(n-j+1)] +
matr1[i, 1:(n-j+1)] * matr2[j , x[i]]
}
}
我应该将其更改为:
public async Task<string> DoSomething() {
return await SomeOtherFunctionThatReturnsATask();
}
或者它真的没关系?
答案 0 :(得分:19)
是的,您应该更改方法并删除async / await。 async
关键字使编译器创建一个管理等待&#39;的状态机。完成任务。当你等待这样的另一个函数时,你实际上创建了两个不必要的状态机。直接从第二个函数返回任务并允许任务的最终使用者进行等待会更好。
理解这一点的最好方法是编写一个小样本程序并对其进行反编译。确保您的反编译器向您显示所有编译器生成的东西(默认情况下隐藏了一些东西),您将能够看到那里发生了什么。
这是一个简单的例子,我刚刚掀起并使用dotPeek反编译:
public Task<string> DoSomething()
{
Class1.\u003CDoSomething\u003Ed__0 stateMachine;
stateMachine.\u003C\u003E4__this = this;
stateMachine.\u003C\u003Et__builder = AsyncTaskMethodBuilder<string>.Create();
stateMachine.\u003C\u003E1__state = -1;
stateMachine.\u003C\u003Et__builder.Start<Class1.\u003CDoSomething\u003Ed__0>(ref stateMachine);
return stateMachine.\u003C\u003Et__builder.Task;
}
private Task<string> DoSomethingElse()
{
return Task.FromResult<string>("test");
}
你可以看到我所指的第一个状态机。它将毫无理由地做所有等待的工作,然后DoSomething()
的最终消费者将重复同样的工作。实际上,只有在其他代码的方法中,其他代码才能真正使用await
关键字>> 返回任务的代码。因为该代码需要等待才能在运行之前完成。
完整反编译代码:http://pastebin.com/iJLAFdHZ