VB.NET: What happens if I run CPU bound code using Await?

I am trying to understand async / await. I understand that you shouldn't wait for a processor bound method, but to help me figure it out, I'm curious what happens if you do. Consider:

Public Async Function DoSomeTasks()
    Await LongRunningCPUBoundMethod1()

    LongRunningCPUBoundMethod2()
End Function

Public Async Function LongRunningCPUBoundMethod1() As Task
     ' Do stuff synchronously
End Function

Public Sub LongRunningCPUBoundMethod2()
     ' Do stuff synchronously
End Sub

      

How will the Task Scheduler handle CPU resources? In what order will these methods be executed? Will the first run LongRunningCPUBoundMethod1 or LongRunningCPUBoundMethod2?

+3


source to share


2 answers


Keep in mind that Async

/ is Await

not necessarily multithreaded. You can use them to help with multi-threaded code by waiting for elements that start a separate thread, but what they do is effectively expose multiple tasks in a single thread.

There is no overhead involved; switching between asynchronous tasks has a cost. When you anticipate CPU bound tasks, you've added that cost to CPU intensive work and therefore made things worse, not better. However, if you combine this with code that runs heavy cpu tasks in a separate thread, and then uses WaitHandle or Task to send the results back, you might be fine again (depending on how many items you expect relative to the number of available cores ) because you are now taking advantage of multiple cores in your processor.

Also, let's look at this in the context of .Net WinForms. The important thing to remember here is that you never want to do significant CPU work on the main UI thread. Indeed, anything that blocks for more than a few milliseconds is problematic. If this thread is busy, the Windows Message pump will not start, you cannot respond to events, and your user interface becomes unresponsive.



To understand Await

in this context, think of it as if it is splitting your method into two parts (or more if there is more than one Await

). Everything before and including line c Await

is executed immediately, and everything after waiting is hidden 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 finished Await

.

With this information, it should be clear that if you directly Await

cpu-bound method, you are still doing this work directly on the UI thread and your UI is still in a quandary. However, you can explain this again by running the cpu-bound method on your own thread. Await

, when combined with Task

s, is relatively easy to do without having to write a lot of new code. Of course, this is much better than the old method DoEvents()

.

+5


source


Execution order.

1.) LongRunningCPUBoundMethod1 ()

2.) LongRunningCPUBoundMethod2 ()



This is how you can mess with program flow and allocation

var task = LongRunningCPUBoundMethod1();
LongRunningCPUBoundMethod2();

var result = await task;
// now result contains what was returned by LongRunningCPUBoundMethod1()

      

Sorry, I don't know how await / async affects CPU resources.

+1


source







All Articles