简体   繁体   中英

Should I use async/await for every method that returns a Task [duplicate]

Suppose I have a C# controller that calls into some arbitrary function that returns a Task (for instance because it performs a database transaction). Should I always use async and await, or should I just return the task?

Example controller:

public async Task<string> DoSomething() {
    return await SomeOtherFunctionThatReturnsATask();
}

Should I change this into:

public Task<string> DoSomething() {
    return SomeOtherFunctionThatReturnsATask();
}

Or does it really not matter?

Yes, you should change the method and remove the async/await. The async keyword causes the compiler to create a state machine that manages the 'waiting' for the task to complete. When you await another function like that, you're essentially creating two of these state machines which is unnecessary. It's much better to just return the task from the second function directly and allow the final consumer of the task to do the waiting.

The best way to understand this, is to write a small sample program and decompile it. Make sure your decompiler is showing you all the compiler generated stuff (which some hide by default) and you will be able to see what all is going on there.

Here's a quick example I just whipped up and used dotPeek to decompile:

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");
}

You can see the state machine in the first one that I was referring to. It's going to do all that work of await'ing for no reason, and then the final consumer of DoSomething() is going to repeat that same work. Realistically you should only really use the await keyword when there is other code in the method that needs to be run after the code that returns the task. Because that code needs to a wait for it to complete before it runs.

Full decompiled code here: http://pastebin.com/iJLAFdHZ

You would return a task to avoid creating a state machine. But as it turns out it seems recommended to prefere async task over just task.

https://github.com/davidfowl/AspNetCoreDiagnosticScenarios/blob/master/AsyncGuidance.md#prefer-asyncawait-over-directly-returning-task

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM