Stephen Toub describes in his article "The Task-based Asynchronous Pattern" that async methods that implement the Task-based Asynchronous Pattern (TAP) may even use a specific thread such as the UI thread to execute their code. That involves that async methods are allowed to use the calling thread. In this case the async method is not really async and blocks the calling thread. Is that really allowed? It wouldn’t make sense to create an async method that blocks the calling thread, or does it?
Here is the relevant clause of Stephen’s article:
Target Environment
It is up to the TAP method’s implementation to determine where asynchronous execution occurs. The developer of the TAP method may choose to execute the workload on the
ThreadPool, may choose to implement it using asynchronous I/O and thus without being bound to a thread for the majority of the operation’s execution, may choose to run on a specific thread as need-be, such as the UI thread, or any number of other potential contexts. It may even be the case that a TAP method has no execution to perform, returning aTaskthat simply represents the occurrence of a condition elsewhere in the system (e.g. aTask<TData>that representsTDataarriving at a queued data structure).
The fact that the method (or part of it) may need to run on the UI thread doesn’t mean it has to block, whether you call it from the UI thread or not.
Imagine you have a method
Task DownloadAndShowData(), that asynchronously downloads some data and then shows it in the UI. To show the downloaded data on the UI, it needs to execute some code on the UI thread. You could implement it something like this:Here,
uiSchedulerFactoryis aTaskFactorythat executes the code on the UI thread (usingSynchrnonizationContext).In this code, the returned
Taskis completed only after the data is shown in the UI, which used the UI thread. But the method itself doesn’t block. If you have a code like:executing on the UI thread, what happens is that when the
awaitis reached, the current method is “paused”, and the UI thread is freed. After the download finishes,ShowData()from above is executed on the UI thread (it can execute, there is nothing blocking the thread). After that is done, the calling method is “unpaused” and// some more codeexecutes.To sum up, an async method execute some code on the UI thread (which could also be where the calling code is executing), but the async method does not block.