0

Is it better to use the async/await keyword when passing a function to a method?

private async Task<int> DoSomethingAsync(Func<Task<int>> innerMethod) {
   DoStuff();
   var value = await innerMethod();
   return value;
}

private async Task<int> GetValueAsync() { 
   // do stuff with await
   return 5;
}

private async Task RunAsync() { 
   // Are there any differences between the following:
   var resultOne = await DoSomethingAsync(async () => await GetValueAsync());
   var resultTwo = await DoSomethingAsync(() => GetValueAsync());
}

Which would be preferred as they both will return the same result?

SamIAm
  • 2,241
  • 6
  • 32
  • 51
  • The results will be the same, however this `async () => await GetValueAsync()` is an inefficient way of achieving `DoSomethingAsync(() => GetValueAsync())` Your choice.. This also could be shortened to a method group `await DoSomethingAsync(GetValueAsync);` – TheGeneral Jan 19 '21 at 03:22
  • Does this answer your question? [What is the purpose of "return await" in C#?](https://stackoverflow.com/questions/19098143/what-is-the-purpose-of-return-await-in-c) – Theodor Zoulias Jan 19 '21 at 04:50
  • [Keep the `async`/`await` keywords unless the expression is trivial](https://blog.stephencleary.com/2016/12/eliding-async-await.html). In this case, it's fine to elide the keywords because the expression is trivial. – Stephen Cleary Jan 19 '21 at 12:43

2 Answers2

3

If GetValueAsync() was to throw an exception, your stacktrace will look slightly different for the 2. The async lambda will include the line number for await GetValueAsync() with the very informative name of the statemachine's MoveNext() function as the point of failure, that's due to awaiting GetValueAsync.

The second option will not have it in the stacktrace as essentially you're eliding the call.

JohanP
  • 5,252
  • 2
  • 24
  • 34
1

Adding "async" forces the compiler to build a state machine. Each execution of the state machine will require a new instance to be allocated on the heap. This adds memory and runtime overheads.

    public Task<int> E1() => Task.FromResult(1);
    public async Task<int> E2() => await Task.FromResult(2);

See SharpLabs for IL disassembly.

If your method is only going to await a Task and immediately return the value, then just returning the Task directly will be much simpler at runtime.

For this reason it is sometimes useful to split other async methods into two parts. A simple method that can return immediately in some cases, and a private async method that is only called when needed.

Jeremy Lakeman
  • 9,515
  • 25
  • 29