Thomas Carlton
Thomas Carlton

Reputation: 5986

How to run tasks in Parallel?

I have the following code which consists of two methods that I want to run in parallel : LoopA and LoopB

Sub Main(args As String())
    Proceed()
End Sub

Public Async Function Proceed() As Task
    Task.WaitAll(LoopA, LoopB)
End Function

Private Function LoopA() As Task
    While True
        Threading.Thread.Sleep(1000)
        Console.WriteLine("A")
    End While
End Function

Private Function LoopB() As Task
    While True
        Threading.Thread.Sleep(1000)
        Console.WriteLine("B")
    End While
End Function

When running this code, the two tasks don't run in parallel. I'm getting only A, A, A...

enter image description here

Can anyone tell me why these tasks aren't running in parallel ?

Thanks

Upvotes: 0

Views: 1541

Answers (2)

Craig
Craig

Reputation: 2494

Async and Await do not automatically put things into different threads. In and of themselves, the only functionality they have is to set things up so that if there is some kind of processing that can be done behind the scenes, then control will return to the UI until the processing concludes.

One common use case for Async and Await doesn't even involve threading, per se. It involves IO, which will run entirely on the main thread (see Stephen Cleary's "There Is No Thread" blog article).

Async and Await are useful helpers for making interaction with parallelism better and more natural, but you will have to introduce the parallelism yourself. For CPU-bound processing which is already being done in the context of Tasks, the best way to do this is using Task.Run, which is covered in jmcilhinney's excellent answer.

Upvotes: 0

jmcilhinney
jmcilhinney

Reputation: 54487

Your methods aren't asynchronous.

Sub Main(args As String())
    Proceed()
End Sub

Public Function Proceed() As Task
    Task.WaitAll(LoopA, LoopB)
End Function

Private Async Function LoopA() As Task
    Await Task.Run(Async Function()
                       While True
                           Await Task.Delay(1000)
                           Console.WriteLine("A")
                       End While
                   End Function)
End Function

Private Async Function LoopB() As Task
    Await Task.Run(Async Function()
                       While True
                           Await Task.Delay(1000)
                           Console.WriteLine("B")
                       End While
                   End Function)
End Function

If you're not going to actually write those methods so that they are asynchronous then they should each be a Sub rather than a function and you can add the asynchronicity when you call them:

Sub Main(args As String())
    Proceed()
End Sub

Public Function Proceed() As Task
    Dim taskA = Task.Run(AddressOf LoopA)
    Dim taskB = Task.Run(AddressOf LoopB)

    Task.WaitAll(taskA, taskB)
End Function

Private Sub LoopA()
    While True
        Threading.Thread.Sleep(1000)
        Console.WriteLine("A")
    End While
End Sub

Private Sub LoopB()
    While True
        Threading.Thread.Sleep(1000)
        Console.WriteLine("B")
    End While
End Sub

Upvotes: 3

Related Questions