Reputation: 553
I have the following sub in my program:
public sub RunThis()
Me.Hide()
NEWFORM.Show()
Dim t = New Thread(Sub() Me.printToPowerPoint(saveLocation, printlist))
t.SetApartmentState(ApartmentState.STA)
t.IsBackground = True
t.Start()
While t.isAlive
end while
NEWFORM.close()
Me.Close()
end sub
Running this my program hangs. Does anyone have a solution for this problem. I am new to threading.
Upvotes: 0
Views: 864
Reputation: 43743
As you probably know, in WinForm projects, the UI can only be dealt with from a single thread. This is affectionately known as the UI thread. That's why, any time you need to access or modify a UI element, you must call the control or form's Invoke
method. The Invoke
method causes the given delegate to be run on the UI thread. However, doing so will not interrupt any processing that is already being performed by the UI thread. If the UI thread is currently busy, when you call Invoke
, it will hang until the UI thread is no longer busy, then it will execute the given delegate.
So, in your code, you are starting a new thread which inside it is trying to invoke a method back on the UI thread. However, immediately after starting the new thread, you then enter a loop which keeps the UI thread busy until the other thread is done. So, when your new thread invokes back to the UI thread, the UI thread is busy and both threads are effectively hung forever.
DoEvents
is a keyword you can call from within a lengthy process or loop in the UI thread to signal that you want to, essentially, pause your current processing thereby freeing up the UI thread to process any waiting window messages (painting events, click events, invoke requests, etc.). As soon as all those pending window messages are processed, it will return to doing whatever the next statement is after you called DoEvents
. Therefore, if calling DoEvents
inside the loop causes it to work properly, that means that your new thread must be invoking back onto the UI thread, or waiting for some other window message to be processed before continuing.
Calling DoEvents
is dangerous and widely panned as being bad practice. Typically, if you need to call DoEvents
, it's a sign that you need to rethink your design. Usually there is a better way to do what you are doing.
In your case, it looks like starting the new thread is utterly pointless. Unless you have abbreviated you code, it appears that as soon as you start the new thread, you simply put the UI thread on hold waiting for the other thread to finish. If that's the case, it would make much more sense to simply do the work on the UI thread itself rather than starting a new one. In the code you provided, no two threads will ever be effectively be doing processing at the same time, so it's no better than a single thread.
Upvotes: 2