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.
Related
This is my code, it works only on form load or click.
But I need to show this msgbox when process close while my app running.
Dim p() As Process
p = Process.GetProcessesByName("notepad")
If p.Count > 0 Then
' Process is running
MsgBox("Running!")
Else
' Process is not running
MsgBox("Not running!")
End If
So, you want to monitor the status->Running or status->NotRunning of a process,
while your Application is executing.
This requires a method that continuously updates the Status of a monitored foreign process.
How this method works, depends on you application functionality:
Is invisible and becomes visible/operable when the monitored process
starts?
Operates indipendently from this foreign process, but takes special
actions when this other process becomes active?
Executes visible and its only purpose is to monitor the foreign
process?
Other
First take a look to:
Check if process is done in VB.Net
application closes itself when another program closes?
Wait for a specefic program to open before continue VB.NET
I suggest you learn how to instantiate a BackgroundWorker.
It's a very straightforward and helpful tool to use if you don't want to manually control an Asynchronous task.
A BackgroundWorker can be instructed to notify your main process (application) that a defined condition has changed.
When this condition is met, the BW raises an Event, letting you know what happend or changed.
Then you decide how to proceed, or - if it is the case - you can terminate the activity of the BackgroundWorker.
Give it a try.
I'm developing a tiny UDP console to send some data to test some GPRS devices so I modify an example that I found in CodeProject that it uses one thread; but I get an issue when I want to exit the application, the treahd refuses to stop even if I do something like
If UdpOpen Then
ThreadReceive.Abort()
Me.Dispose()
UdpOpen = False
End If
It halt on the first code line
Private Sub UdpReceive()
Dim receiveBytes As [Byte]() = receivingUdpClient.Receive(RemoteIpEndPoint) '<--Halt here
IpRemote(RemoteIpEndPoint.Address.ToString)
Dim BitDet As BitArray
BitDet = New BitArray(receiveBytes)
Dim strReturnData As String = System.Text.Encoding.ASCII.GetString(receiveBytes)
If UdpOpen Then
StartUdpReceiveThread(CInt(RemotePortLbl.Text))
End If
PrintLog(strReturnData)
End Sub
So I do some research and found, usually, in this Web page the solution
Stop a thread that prevents program to close?
And, as says on the first comment, I turn to True the isBackground property and it work, now the question is Why?
Does somebody knows more in deep how it works?
A thread is only abortable when the CLR knows that it is safe to do so. Which will not be the case when the thread is buried deep inside an operating system call. That is fundamentally unsafe since the CLR cannot know if the thread has acquired any internal operating system locks that need to be released again.
By setting the IsBackground property to true, you tell the CLR that it is okay for the thread to not be aborted but leave it up to the operating system to clean-up anything that needs to released. Any taken locks cannot cause any problems anymore since there is no way for any code to run anymore that could deadlock. The operating system takes care of releasing the OS resources used by the socket. Much as it does if your program aborts for any other reason, like you terminating it with Task Manager.
The proper way to do this is to just call the socket's Dispose() method. That pulls the floor mat on the operating system call, it will stop waiting for anything to be received because the socket is a dead parrot. The Receive() call will complete with an ObjectDisposedException, be prepared to catch it.
Another very common scenario is to not use a thread at all but to use BeginReceive(). Cleanup works much the same way, when you call Dispose() then the callback will run. When you call EndReceive() then you get the ObjectDisposedException. Same way, be prepared to catch it and get out quick without doing anything else with the socket.
Using Thread.IsBackground is otherwise a pretty reasonable way to deal with shutdown, assuming you don't have to do anything intricate to tell the program on the other end of the wire that you stop listening for messages.
.NET has built-in support for receiving UDP asynchronously. See this:
UdpClient.BeginReceive
So you don't need to use threads in this case.
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.
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.
VB.NET 2010, .NET 4
Hello all,
I have a System.Timers.Timer object that does some work on its elapsed event:
Private Sub MasterTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles MasterTimer.Elapsed
MasterTimer.Enabled = False
'...work...
MasterTimer.Enabled = True
End Sub
My problem is that the work that it's doing sometimes gets stuck. Part of the work is serial communication so it might be getting stuck waiting for a response from something. I've already modified my serial communication code a bit to hopefully solve the problem. However, this timer is basically the heartbeat of a production control application and it is very bad if it were to stop for any reason. I was thinking that it might be nice to put in a fail-safe timeout so that, if the "work" is taking too long, the timer could re-enable itself and try again. I was thinking of something like this:
Move the work into a subroutine and create a delegate:
Private Delegate Sub WorkDelegate()
Private Sub Work()
'...work...
End Sub
Call the work by invoking the delegate and then use WaitOne(timeout) on the IAsyncResult to specify a timeout:
Private Sub MasterTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles MasterTimer.Elapsed
MasterTimer.Enabled = False
Dim workDel as New WorkDelegate(AddressOf Work)
Dim result as IAsyncResult = workDel.BeginInvoke
result.AsyncWaitHandle.WaitOne(CInt(MasterTimer.Interval))
MasterTimer.Enabled = True
End Sub
But, my question is: Would this cause a problem if Work() really was stuck somewhere? In that it would re-enter a subroutine that is already running? Is there a way to abort Work() if it hasn't finished after the timeout? In other words, just cease execution of Work() if result.IsCompleted Is False after WaitOne?
I don't really understand this stuff very well so, any comments would be greatly appreciated. Perhaps there's an entirely different way to approach this that I don't know about?
Thanks a lot in advance!
I would like to add something:
Although I intend to do some rewrites as per Hans' suggestions, I had already scheduled a day of testing to try to isolate the source of this error. So far, it has only occurred when running the compiled application. I have spent today (and some yesterday) trying to reproduce the freeze while running in debug mode so that maybe I could add some breakpoints and figure out what's going on. So far, the program hasn't frozen in debug mode. I'm just wondering if there's anything different about the debug environment that might explain this. It might just be that I'm being "lucky", but I've run it probably three times the average time length after which the program froze when running the executable... Again, I'm pretty ignorant, but is there anything unique about the debug environment that could explain this? I'll update again if it freezes.
This goes wrong on the very first line of the code. The System.Timers.Timer class is pretty icky, there's absolutely no guarantee that call Stop() will prevent another call. The timer uses ThreadPool.QueueUserWorkItem to make the Elapsed event handler call. If the threadpool is busy this may end up queuing several calls, waiting to get the go-ahead from the TP scheduler to start running. Stopping the timer doesn't prevent those waiting threads from running. Without using a lock, those threads will step on each other badly and mess up your communication state.
A safe one is System.Threading.Timer with a period of zero so you'll get only one callback. Recharge the timer with its Change() method.
Calling a delegate's BeginInvoke() method and then blocking on it completing doesn't make sense. Just call Invoke(). Saves you from burning up another thread.
Yes, if the 'Work' method never returns then you have a problem. An unsolvable one.
A lot of this misery could disappear if you avoid using polling to see if there's anything available on the serial port. Let it tell you that there's something worthwhile going on. It raises the DataReceived event, on a threadpool thread, whenever there's at least one byte in the receive buffer. Using its WriteTimeout property is also an excellent way to avoid getting stuck when something is amiss with the communication protocol or the device. Dedicating one Thread and making blocking Read calls works well too.