Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is using an an `async` lambda with `Task.Run()` redundant?

I just came across some code like:

var task = Task.Run(async () => { await Foo.StartAsync(); });
task.Wait();

(No, I don't know the inner-workings of Foo.StartAsync()). My initial reaction would be get rid of async/await and rewrite as:

var task = Foo.StartAsync();
task.Wait();

Would that be correct, or not (again, knowing nothing at all about Foo.StartAsync()). This answer to What difference does it make - running an 'async' action delegate with a Task.Run ... seems to indicate there may be cases when it might make sense, but it also says "To tell the truth, I haven't seen that many scenarios ..."

like image 957
Ðаn Avatar asked Sep 15 '15 16:09

Ðаn


People also ask

What is an async lambda?

For asynchronous invocation, Lambda places the event in a queue and returns a success response without additional information. A separate process reads events from the queue and sends them to your function. To invoke a function asynchronously, set the invocation type parameter to Event .

Does async await improve performance?

C# Language Async-Await Async/await will only improve performance if it allows the machine to do additional work.

What does Task run do C#?

The Run method allows you to create and execute a task in a single method call and is a simpler alternative to the StartNew method. It creates a task with the following default values: Its cancellation token is CancellationToken.

What is the difference between async method and task run()?

Async methods, like your example of Foo.StartAsync (), should always return a Task object. This means that using Task.Run () to create another task is usually redundant in an async method. The task returned by the async method can simply be awaited by using the await keyword.

Why can't I use task run in a library method?

This is why library authors are discouraged from using Task.Run in library methods: It should be up to the caller when threads are launched. Therefore, it's generally recommended that you put calls to Task.Run as close to the UI code and event handlers as possible.

Does async/await work with Task run in ASP core?

Thus far we've talked about UI-based applications, but does this information about Task.Run apply to a web application framework such as ASP.NET Core? There are certainly a number of advantages to using async/await with ASP.NET Core, but the same cannot be said for Task.Run.

What is the use of task run method in Java?

The Run method queues code to run on a different thread (usually from the "thread pool", which is a set of worker threads managed for your application by .NET). And, importantly, Task.Run returns a Task which means you can use the await keyword with it!


2 Answers

Normally, the intended usage for Task.Run is to execute CPU-bound code on a non-UI thread. As such, it would be quite rare for it to be used with an async delegate, but it is possible (e.g., for code that has both asynchronous and CPU-bound portions).

However, that's the intended usage. I think in your example:

var task = Task.Run(async () => { await Foo.StartAsync(); });
task.Wait();

It's far more likely that the original author is attempting to synchronously block on asynchronous code, and is (ab)using Task.Run to avoid deadlocks common in that situation (as I describe on my blog).

In essence, it looks like the "thread pool hack" that I describe in my article on brownfield asynchronous code.

The best solution is to not use Task.Run or Wait:

await Foo.StartAsync();

This will cause async to grow through your code base, which is the best approach, but may cause an unacceptable amount of work for your developers right now. This is presumably why your predecessor used Task.Run(..).Wait().

like image 77
Stephen Cleary Avatar answered Sep 30 '22 18:09

Stephen Cleary


Mostly yes.

Using Task.Run like this is mostly used by people who don't understand how to execute an async method.

However, there is a difference. Using Task.Run means starting the async method on a ThreadPool thread.

This can be useful when the async method's synchronous part (the part before the first await) is substantial and the caller wants to make sure that method isn't blocking.

This can also be used to "get out of" the current context, for example where there isn't a SynchronizationContext.

like image 25
i3arnon Avatar answered Sep 30 '22 17:09

i3arnon