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.
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.
Related
I'm new to threading, so there are a few things I'm trying to grasp correctly.
I have a windows form application that uses threading to keep my UI responsive while some server shenanigans are going on.
My question is: when I quit my application, what happens to ongoing threads? Will they run to completion or will the abruptly be interrupted?
If they are interrupted, what can I do to make sure they at least don't get interrupted in such a way that would corrupt data on my server (force them to run to a safe place in the code where I know it's ok to interrupt the execution)
You will want to keep a reference of said threads, and call .Abort() on them when you want to terminate. Then you put your thread's code in a try/catch block and handle ThreadAbortException's. This will let you clean up what you are doing and terminate the thread cleanly at your own pace. In the main thread, after you called .Abort(), you just wait until the thread is no longer running (by polling the .IsAlive property of the Thread object) and close your application afterwards.
A thread needs a process to run in. The process won't be able to terminate if you don't terminate all the non-background threads you have started. Threads marked as background thread will be aborted.
So, the behavior is entirely up to your implementation. If you want to close the application, you could wait for all threads to terminate by themself, you could set an event to ask them to terminate and wait or you could just kill the threads.
The UI thread will terminate by itself because it runs a messageloop that stops when requested by the operating system, also see wikipedia and this answer.
I cannot implement workerthreads since there are already too many classes developed with their own threads which call upon methods. It seems that, if there is any looping code to monitor completion of running threads, the only way to allow the started threads to complete their work is to feed them "sleep" time. Otherwise, sitting on a WaitOne outside of a thread or attempting anything using a Do-While loop to wait for threads to complete is difficult to successfully perform.
Below is my code which monitors completion of threads in a ThreadList, which works most of the time, however, I traced through breakpoints in a running Method (which was fired via a thread in an instantiated class), and the code simply determined that the thread completed, so execution left the method and continued in the external thread completion-monitoring code.
Do you see any problems in the code below which would cause a thread to falsely signal it was completed, causing execution to leave the For loop below? Also, will an overabundance of thread sleep time be added to memory using this approach?
startagain:
For Each t In threadList
If t.ThreadState = Threading.ThreadState.Stopped = False Then
wait(1)
GoTo startagain
End If
If t.ThreadState = Threading.ThreadState.Stopped = True Then Exit For
Next
Private Sub wait(ByVal seconds As Integer)
For i As Integer = 0 To seconds * 100
System.Threading.Thread.Sleep(10)
Application.DoEvents()
Next
End Sub
Visual Studio's debugger will switch from thread to thread if the breakpoints are there since they run concurrently. I believe that explains this part of your question "so execution left the method and continued in the external thread completion-monitoring code".
I speculate your problem is that you exit the for loop if a single thread is stopped, yet you are iterating through a list of threads. REMOVE this code and I believe your issue will be resolved:
If t.ThreadState = Threading.ThreadState.Stopped = True Then Exit For
Finally, here is a good MSDN link that describes different multithreading debugging techniques using Visual Studio.
I am running code in a thread upon opening an Excel workbook that takes some time to execute. If I attempt to close the workbook while the thread is still executing, giving me the standard prompt to Save or cancel, my thread is interrupted (not sure if "interrupted" is technically the right term) when I click Cancel. More generally, it seems that UI interactions/updates cause the thread to be interrupted.
Is there a way to either 1) prevent the thread from being halted by a UI update/user interaction, or 2) allow the thread to resume after being interrupted?
Nothing fancy about the code:
Private Shared Sub Test()
Dim t As New Thread(AddressOf DoSomethingThatTakesAWhile)
t.Start()
End Sub
I made a bunch of progress on this, but ultimately could not get this to work using my original approach. So, I switched to .Net Framework 4.0 and used Tasks (System.Threading.Tasks namespace) to handle the job. Tasks worked beautifully and intuitively, and removed much of the complexity around thread management.
I am trying to use a separate thread to handle specific events in VB.Net. The idea being that I do not want the main application to be held up if a particular event handler takes awhile to finish. How do I get my main thread loop to suspend the thread while allowing it to handle events when they occur?
When I create a Windows Forms application, there is a UI thread that handles the UI events. I do not imagine that this thread is continuously polling some variable to see if someone has pressed a button. I imagine the thread is suspended until the OS tells it there is something to do. I was trying to figure out how to ensure that my event handlers were not being executed by the UI thread. From what I have read, I can do this by raising the events from a different thread. But what does that thread do while it is waiting for other events, just exit?
I wanted to know how to create a thread that works like the UI thread, only it processes the events I want it to process. I am not sure how events work in .Net. I understand that event handlers are run on the thread that raises the event. I believe that .Net allocates threads from some thread pool to process events such as timer events. I am not clear on how it works, though, and what those threads are doing when they are not handling events.
Based on your comments I can see that what you want can best be solved by using the producer-consumer pattern. With this pattern the consumer thread is constructed and started in such a manner that it spins around a loop indefinitely waiting for items to appear in a queue. A UI thread will use this same pattern to implement its message loop. Here is how it works.
public class DedicatedProcessingThread
{
private BlockingCollection<object> m_Queue = new BlockingCollection<object>();
public Consumer()
{
new Thread(
() =>
{
while (true)
{
object item = m_Queue.Take(); // This blocks until an item appears.
// Do something with item here.
}
}).Start();
}
public void Post(object item)
{
m_Queue.Add(item);
}
}
The magic happens in the Take method. This method is designed to "suspend" (your terminology, not mine) or change the state of the thread to WaitSleepJoin while the queue is empty. Once an item is queued the consuming thread wakes up and the Take method returns the next item. That is the general pattern used in the message loop of a UI thread except instead of queueing plain old object instances Windows is posting System.Windows.Forms.Message values. You could do something similar by posting Delegate instances that would then be processed on the consumer thread once they arrive.
You can have the current thread sleep for a specified amount of milliseconds:
Threading.Thread.Sleep(100)
This will sleep for 1/10sec.
However if you need queued events to happen on the current thread, you can use:
Application.DoEvents()
The primary issue with using DoEvents is you don't know how much work actually gets done so it can be somewhat unreliable depending on what you are trying to accomplish.
How can I make my thread sleep first before it runs? I know how to get sleep to work, however, whenever my program is run, the thread immediately runs. I want it to WAIT once it is first created to start running. (I am using handlers)
You cannot control when threads are scheduled. If you want it to go to sleep, have the first statement in the thread subroutine do a wait on a condition or something like that and when you are ready you can broadcast to that condition. In pseudo-code:
get-lock
if (we-are-still-supposed-to-sleep)
pthread_cond_wait()
release-lock
I suppose you could have the parent hold the lock while creating the children and then all they have to do is:
get-lock
release-lock
and avoid the condition thing.
What OS? Windoze allows you to create threads in a suspended state. When you have loaded up the thread fields in the ctor, you can resume the thread. Failing that, pass some synchro object in the thread start parameter for the new thread to wait on.
Rgds,
Martin.