Various methods for completing an empty asynchronous task

I am using a library that has both a synchronous and async version of the Reconcile method.

The methods accept 2 IEnumerables and 3 delegates who receive calls for items that are added, changed, or removed from the second list based on the values ​​from the first.

My code currently works with the synchronous version and I would like to convert it to the async version.

Since I really don't need to do any deletion work to delete, I pass (item) => {} for the deletedAction argument.

I found several different versions of how to convert this to an async “empty” delegate scattered all over the Internet and through StackOverflow, but I'm not sure about the difference between them or how it is correct.

What is the difference between these methods of sending an "empty" async delegate as an argument, and which one is the current "most correct" way? Is there a better way that I skipped?

  • async (item) => {await Task.CompletedTask;}
  • async (item) => {await Task.FromResult(0);}
  • async (item) => {await Task.Yield;}
  • async (item) => {await Task.Delay(0);} (this seems like a bad choice, but I turn it on for completeness)

All of them work, except for Task.CompletedTask , but this is because I use the framework version 4.5.NET Framework and do not exist in this version.

+5
source share
1 answer

Therefore, none of them is correct. What you should do:

 item => Task.CompletedTask 

Or, if on an older version of the frame:

 item => Task.FromResult(0) 

You have no reason to make an async method just to wait for a task that has already been completed. It just adds the overhead to the state machine to do nothing.

Using Delay simply goes through an extra layer of indirection before returning the completed task. This does not add anything useful other than hiding the fact that you are trying to return a completed Task . He also relies on an undocumented implementation detail that Delay returns the completed task when the timeout is 0 , which can be avoided where possible.

Using Yield is by far the worst. The whole point of Yield is that it will not be considered complete immediately. The purpose of Yield is to lead to the addition and launch of a continuation, and not to the completion of a task immediately. It exists specifically to avoid the optimization you want to use.

+6
source

Source: https://habr.com/ru/post/1275743/


All Articles