According to answer of Stephen Cleary in answer https://stackoverflow.com/a/19098209/3107892, and his linked blog post, the only difference is that the second one creates a state machine. Here you can use the first case without any downside.
Here are some guidelines that you can follow:
- Do not elide by default. Use the async and await for natural, easy-to-read code;
- Do consider eliding when the method is just a passthrough or overload;
- Do not elide if you want the method to show up in your stack trace.
Just to be complete, based on another answer here:
Task.Run(Func<Task>)
will queue the result of the function on the thread pool and the resulting function will finish when the queued task finishes (including all awaits)
Task.Run( MethodA );
will convert the method to a delegate and pass this on.
Task.Run( () => MethodA() );
will create a hidden method that will return the result of MethodA
(it's this hidden method that will be converted to a delegate and passed on).
Task.Run( async () => await MethodA() );
will create a hidden method that contains the await, but as stated earlier, this will be converted to a state machine that in the end wraps the result of MethodA()
in a new Task
.
Task.Run( () => { MethodA(); } );
is something completely different, because of the curly brackets, this will call the Task.Run(Action)
overload and in this case the MethodA()
will run on this task until it hits the first uncompleted await and then finish. What happens after this inner task completes (after the inner await) will not be monitored by this Task.Run
but will keep running on the thread pool and if it throws an exception, can cause your application to crash. The reason for this is that the task that MethodA
returns is ignored due to the lack of the keyword return
.
Task.Run( () => { return MethodA(); } );
is a fix for this exception and will work just as all the other examples.