'what's the benefit of running async code with task.run() [closed]
It's hard for me the fathom the benefit of offloading asynchronous work to Task.Run(). there have been many questions about async work being offloaded to a Task before, but I have never seen, what is for me the biggest mystery, being addressed.
consider two options:
- option1:
var t1= Task.Run( async() => { await CPUBoundWorkAsync(); });
- option2:
var t2= Task.Run( () => { CPUBoundWork(); });
With the 2nd option, the work is being offloaded to a separate thread, thus asynchronicity is "achieved", and the main thread can get back to whatever it's needed for. With the 1st option, the Async method is used and the delegate is expressed as Async. Both options should yield indistinguishable result in terms of not blocking the main thread, and having the CPU bound work finish at the same time. Is there a benefit from using the Async method in Task.Run ? it seems to me this is essentially letting the work that is already being ran asynchronously (on a different non blocking thread), to also run itself asynchronously. Can the the thread pool or whatever manages those task threads read into this? and then perhaps give that awaiting thread some other work to do ? if this is the case I haven't seen it mentioned in any expert blog post, or relevant page on the internet.
Solution 1:[1]
With the 2nd option, the work is already being offloaded to a separate thread, then the asynchronicity is already gained in the scope of the program that invoked t2.
Task.Run doesn't make something asynchronous. It does permit you to run synchronous code on a thread pool thread (and thus blocking a thread pool thread instead of some other thread), but I wouldn't say it "makes it asynchronous". The code is still blocking a thread, synchronously.
Now although the work that is being done in the 1st option is declared and implemented as async, it's essentially letting code that is already being ran asynchronously, to also run itself asynchronously. What benefits from it ? Can the the scheduler or whatever manages those task threads read into this? and then perhaps give that awaiting thread some work on another task ?
Threads don't await. Methods await. When a thread is running a method and hits an await, that method is paused, the method returns to its caller, and the thread continues executing. In the case of a delegate passed to Task.Run, the await will cause the method to return -- to the thread pool, thus returning the thread to the thread pool. When the awaited task completes, a thread from the thread pool will be used to resume executing the method; this may be the same thread or a completely different thread.
More info on how exactly await works is on my blog.
if this is the case I haven't seen it mentioned in any expert blog post, or relevant page on the internet.
I have a series on Task.Run etiquette. Essentially, Task.Run is primarily used to offload synchronous or CPU-bound work off the UI thread in GUI applications. It is also occasionally useful in server-side scenarios if you want to start something processing quickly and loop back around and grab the next thing to process. There are a few other use cases but they are rare.
These reasons can all hold for asynchronous APIs. Sometimes APIs appear asynchronous but aren't actually. Or some methods are asynchronous but they do a nontrivial amount of synchronous work first, so a Task.Run is still desirable in some cases even with asynchronous code.
Solution 2:[2]
In your example, if f1() and f2() are asynchronous (in that they return Task) then the async keyword will allow you to await those inside your Task.Run().
Your question is similar to “why would you mark any method as async”… because you want to run asynchronous code inside. Or more specifically, you’d like the compiler to build the state machine to handle “waiting” for the asynchronous operation to complete.
Solution 3:[3]
I am not sure whether or not I get you question right. Focussing on "it's essentially letting code that is already being ran asynchronously, to also run itself asynchronously":
Although it seems pointless to run async code within Task.Run, there are situations where this can be nesessary. Asynchronous methods always run synchronously until the first "real" asynchronous call happens. A good example is the use of backgroundservices.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Stephen Cleary |
| Solution 2 | Scott Perham |
| Solution 3 | Clemens |
