Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async/Await action within Task.Run()

Tags:

Task.Run(()=>{}) puts the action delegate into the queue and returns the task . Is there any benefit of having async/await within the Task.Run()? I understand that Task.Run() is required since if we want to use await directly, then the calling method will need to be made Async and will affect the calling places.

Here is the sample code which has async await within Task.Run(). The full sample is provided here: Create pre-computed tasks.

Task.Run(async () => { await new WebClient().DownloadStringTaskAsync("");});

Alternatively this could have been done:

Task.Run(() => new WebClient().DownloadStringTaskAsync("").Result;);

Since both, Task.Run() and Await will queue the work and will be picked by the thread pool, could the async/await within the Task.Run() be a bit redundant?

like image 508
Chandan Avatar asked Jan 12 '16 23:01

Chandan


2 Answers

Is there any benefit of having async/await within the Task.Run() ?

Yes. Task.Run runs some action on a thread-pool thread. If such action does some IO work and asynchronously waits for the IO operation to complete via await, then this thread-pool thread can be used by the system for other work while the IO operation is still running.

Example:

Task.Run( async () =>
{
    DoSomeCPUIntensiveWork();

    // While asynchronously waiting for this to complete, 
    // the thread is given back to the thread-pool
    var io_result = await DoSomeIOOperation(); 

    DoSomeOtherCPUIntensiveWork(io_result);
});
like image 171
Yacoub Massad Avatar answered Oct 04 '22 22:10

Yacoub Massad


Is there any benefit of having async/await within the Task.Run()

An async method returns to the caller as soon as the first await is hit (that operates on a non-completed task). So if that first execution "streak" of an async method takes a long time Task.Run will alter behavior: It will cause the method to immediately return and execute that first "streak" on the thread-pool.

This is useful in UI scenarios because that way you can make 100% sure that you are not blocking the UI. Example: HttpWebRequestdoes DNS resolution synchronously even when you use one of the async methods (this is basically a library bug/design error). This can pause the UI thread. So you can use Task.Run to be 100% sure that the UI is never blocked for longer than a few microseconds.

So back to the original question: Why await inside a Task.Run body? For the same reason you normally await: To unblock the thread.

like image 39
usr Avatar answered Oct 04 '22 21:10

usr