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 AsyncRead(); });
- option2:
var t2= Task.Run( () => { Read(); });
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. 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 ? if this is the case I haven't seen it mentioned in any expert blog post, or relevant page on the internet.
CodePudding user response:
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 await
ed 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.
CodePudding user response:
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.
CodePudding user response:
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.