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
And another is main thread
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
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.