Home > Net >  How can await async uses 2 thread?
How can await async uses 2 thread?

Time:12-09

As far as I know, programs using await async uses only 1 thread. That means we do not have to worry about any conflicting threads. When the compiler see "await" it will simply do other things on that same thread till what they're awaiting for is done.

I mean the stuff we're awaiting for may run in another thread. However, the program doesn't create another thread. It simply do something else in that same thread.

Hence, we shouldn't worry about conflicts

Yet, today I discover that something is running on at least 2 different thread

Public Sub LogEvents(ByVal whatToLog As String, Optional ByVal canRandom As Boolean = True) Static logNumber As Integer

Dim timeStamp As String

timeStamp = CStr(Microsoft.VisualBasic.Now)

whatToLog = timeStamp & " " & " " & whatToLog & Microsoft.VisualBasic.vbNewLine

Try
    Debug.Print(whatToLog)
    System.IO.File.AppendAllText("log.txt", whatToLog, defaultEncoding)
...

Looking at the thread.

So one is worker thread

enter image description here

And another is main thread

enter image description here

Both threads stuck at the same place.

What confuses me is I thought everything should have been running on main thread. That's just how await async works. How can anything run on worker thread?

The task is created like this

For Each account In uniqueAccounts().Values
    Dim newtask = account.getMarketInfoAsync().ContinueWith(Sub() account.LogFinishTask("Geting Market Info", starttime))
    LogEvents("marketinfo account "   account.Exchange   " is being done by task "   newtask.Id.ToString   " "   newtask.ToString)
    tasklist.Add(newtask)
    'newtask.ContinueWith(Sub() LogEvents(account.ToString))
Next

This is the screen shot

enter image description here

That is followed by

    LogEvents("Really Start Getting Market Detail of All")
    Try
        Await jsonHelper.whenAllWithTimeout(tasklist.ToArray, 500000)
    Catch ex As Exception
        Dim b = 1
    End Try

That calls

Public Shared Async Function whenAllWithTimeout(taskar As Task(), timeout As Integer) As Task
    Dim timeoutTask = Task.Delay(timeout)
    Dim maintask = Task.WhenAll(taskar)
    Await Task.WhenAny({timeoutTask, maintask})
    If maintask.IsCompleted Then
        Dim b = 1

        For Each tsk In taskar
            LogEvents("Not Time Out. Status of task "   tsk.Id.ToString   " is "   tsk.IsCompleted.ToString)
        Next
    End If

    If timeoutTask.IsCompleted Then
        Dim b = 1
        For Each tsk In taskar
            LogEvents("status of task "   tsk.Id.ToString   " is "   tsk.IsCompleted.ToString)
        Next
    End If
End Function

So I created a bunch of tasks and I use Task.Whenall and Task.Whenany

Is that why they run it on a different thread than the main thread?

How do I make it run on main thread only?

CodePudding user response:

As far as I know, programs using await async uses only 1 thread.

This is incorrect.

When the compiler see "await" it will simply do other things on that same thread till what they're awaiting for is done.

Also incorrect.

I recommend reading my async intro.

await actually causes a return from the method. The thread may or may not be returned to the runtime.

How can anything run on worker thread?

When async methods resume executing after an await, by default they will resume executing on a context captured by that await. If there was no context (common in console applications), then they resume on a thread pool thread.

How do I make it run on main thread only?

Give them a single-threaded context. GUI main threads use a single-threaded context, so you could run this on a GUI main thread. Or if you are writing a console application, you can use AsyncContext from my AsyncEx library.

  • Related