I am trying to understand async/await. I understand that you should not Await a CPU-bound method, but to help my understanding I am curious what happens if you do. Consider:
Public Async Function DoSomeTasks()
Public Async Function LongRunningCPUBoundMethod1() As Task
' Do stuff synchronously
Public Sub LongRunningCPUBoundMethod2()
' Do stuff synchronously
The thing to remember here is that
Await code is not necessarily multi-threaded. You can use them to help with multi-threaded code by awaiting items that start a separate thread, but what they really do is allow you to break up several tasks efficiently in the same thread.
This doesn't come without some overhead; switching between asynchronous tasks has a cost. When you await cpu-bound tasks, you've added that cost to the already cpu-intensive work, and therefore made things worse rather than better. However, if you combine this with code that starts the cpu-heavy tasks in a separate thread, and then uses a WaitHandle or a Task to send the results back, you might be fine again (depending on how many items you're awaiting relative to the number of available cores), because now you're taking advantage of the multiple cores in your CPU.
Additionally, let's look at this in context of .Net WinForms. It's important to remember here that you never want to do significant CPU work on main UI thread. Really, anything that blocks for more than a few milliseconds is problematic. If that thread is busy, the Windows Message pump doesn't run, you can't respond to events, and your user interface becomes unresponsive.
Await in this context, think of it as if it breaks your method up into two parts (or more, if there is more than one
Await). Everything up to and including the line with
Await runs immediately, and everything after the await is hidden away by the compiler in a new callback method (called a continuation) that will be called with the same context (including variables local to the original method) and in the same thread when the
Await has finished.
With this information, it should be clear that if you directly
Await a cpu-bound method, you're still doing that work immediately on the UI thread, and your user interface is still in trouble. However, you can again account for this by starting the cpu-bound method in it's own thread.
Await, in conjunction with
Tasks, make this relatively easy to do without having to write a lot of new code. Certainly it's much better than the old