@H_404_1@假设我有一个C#控制器调用一些返回任务的任意函数(例如因为它执行一个数据库事务).我应该永远使用异步和等待,还是应该只返回任务?
示例控制器
public async Task<string> DoSomething() { return await SomeOtherFunctionThatReturnsATask(); }
我应该把它改成:
public Task<string> DoSomething() { return SomeOtherFunctionThatReturnsATask(); }
还是真的没关系?
解决方法
是的,您应该更改方法并删除异步/等待. async关键字使编译器创建一个状态机来管理任务完成的“等待”.当你等待另外一个这样的功能的时候,你本质上就是创建两个不必要的状态机.最好直接从第二个函数返回任务,并允许任务的最终使用者进行等待.
理解这一点的最好方法是编写一个小样本程序并对其进行反编译.确保您的反编译器显示所有编译器生成的东西(默认情况下隐藏),您将可以看到所有的内容.
这是一个快速的例子,我刚刚鞭打,并使用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