-
Feb 12th, 2021, 04:55 AM
#1
Thread Starter
New Member
Aborting a thread running an infinite loop
Good morning all,
I've come to a problem on a vb.net wpf code that i didn't developed and that I'm not very comfortable with the language.
Basically, i have a PLC-PC communication and i want to update the values on the form on a periodic way.
For that i have a main page, inside that main page i have a Frame, and when change pages i load the new page to the frame, maintaining the main page always running throw-out the program:
Code:
Private Sub buttonIOState_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles buttonIOState.Click
SetCursorPos(0, 0)
Frame1.Content = New IOState
End Sub
When i press the button described on top ( i have 5 of this buttons/pages that the user can freely navigate through ), the page when loaded runs the following code:
Code:
Private Sub Page_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
updateUIThread.IsBackground = True
updateUIThread.Start()
running = True
End Sub
Delegate Sub updateUIDelegate()
Public updateUI2 As updateUIDelegate = AddressOf updateUIfunc
Private Sub updateUIfunc()
textBlockReadPressureT1.Text = intVariables("readingPressureCaixao1").reading
textBlockReadPressureT2.Text = intVariables("readingPressureCaixao2").reading
textBlockReadX1.Text = Format(intVariables("readingX1").reading / 10, "0.0")
textBlockReadX2.Text = Format(intVariables("readingX2").reading / 10, "0.0")
textBlockReadX3.Text = Format(intVariables("readingX3").reading / 10, "0.0")
textBlockReadX4.Text = Format(intVariables("readingX4").reading / 10, "0.0")
End Sub
Private Sub updateUI()
While running
Try
Me.Dispatcher.Invoke(updateUI2)
Thread.Sleep(200)
Catch ex As Exception
MessageBox.Show("Error thread Manual updateUI:" & vbCrLf & ex.ToString)
Exit While
End Try
End While
End Sub
Private Sub Page_Unloaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Unloaded
running = False
Try
System.Threading.Thread.Sleep(50)
updateUIThread.Abort()
Catch ex As Exception
MessageBox.Show("Manual State 2:" & vbCrLf & ex.ToString)
End Try
End Sub
Every time i load a new page into the frame i run the previous code, so that i can upload the values present on the screen in "real-time".
Problem:
- The program overtime is getting slower and slower.
- Most of the times that i change page i get a thread error
I can't know when the thread has finished, because i only want the thread to finish when the page is unloaded.
I've read about Background workers, but I'm not sure that is the correct path.
All help would be appreciated.
Thank you in advance for your time.
-
Feb 12th, 2021, 10:18 AM
#2
Re: Aborting a thread running an infinite loop
I can't really help out but I did want to post a working example of a background worker that forum member put together. Maybe it will give you an idea:
http://www.vbforums.com/showthread.p...ckgroundWorker
Please remember next time...elections matter!
-
Feb 12th, 2021, 11:47 AM
#3
Re: Aborting a thread running an infinite loop
What are you expecting these two lines to do:
System.Threading.Thread.Sleep(50)
updateUIThread.Abort()
UpdateUI has a means to exit, which is by setting running to false. However, UpdateUI is also fairly likely to be sleeping, since it contains a line to sleep for 200. I'm not thrilled with the background thread doing nothing more than setting UI variables, but leave that aside. You appear to be waiting for only 50ms, then aborting the thread no matter what state it's in. Since the thread will sleep for 200ms each loop, it seems like it would be only pure chance whether or not it even got to see that running has been set to False before the 50ms expires and the thread is forcibly aborted.
Basically, why are you waiting only 50ms for the thread to exit normally when you know that the thread can only check to see whether it should exit every 200ms, at best? It seems like you should get rid of those two lines entirely, but if you are afraid that the thread might not exit for some reason (if one of those calls it is making can block excessively), then at the very least you should give it a more generous amount of time to clean itself up. Waiting half a second (500 ms) seems to be considerably more generous of you.
My usual boring signature: Nothing
-
Feb 12th, 2021, 12:19 PM
#4
Thread Starter
New Member
Re: Aborting a thread running an infinite loop
Originally Posted by Shaggy Hiker
What are you expecting these two lines to do:
System.Threading.Thread.Sleep(50)
updateUIThread.Abort()
Basically, why are you waiting only 50ms for the thread to exit normally when you know that the thread can only check to see whether it should exit every 200ms, at best? It seems like you should get rid of those two lines entirely, but if you are afraid that the thread might not exit for some reason (if one of those calls it is making can block excessively), then at the very least you should give it a more generous amount of time to clean itself up. Waiting half a second (500 ms) seems to be considerably more generous of you.
Thank you for your answer.
I've done that, at first i had:
Code:
System.Threading.Thread.Sleep(300)
200 from the thread sleep + 100 of "bonus" but then i was "waiting" for 300 ms for the page to change, and believe me when i say that it was noticable.
UpdateUI has a means to exit, which is by setting running to false. However, UpdateUI is also fairly likely to be sleeping, since it contains a line to sleep for 200. I'm not thrilled with the background thread doing nothing more than setting UI variables, but leave that aside. You appear to be waiting for only 50ms, then aborting the thread no matter what state it's in. Since the thread will sleep for 200ms each loop, it seems like it would be only pure chance whether or not it even got to see that running has been set to False before the 50ms expires and the thread is forcibly aborted.
I need the variables to be constantly updated without losing any button click from the user. How can i achieve that differently?
Should it not be a background thread?
Shoud i just set running to false and exit without the abort? like so:
Code:
Private Sub Page_Unloaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Unloaded
running = False
End Sub
-
Feb 12th, 2021, 12:48 PM
#5
Re: Aborting a thread running an infinite loop
The first thing I would try is just removing the abort. It would be a good experiment.
300ms would be a third of a second delay (roughly). That would be a noticeable stutter, but just barely. If you see something more than that, there may be something else going on. Abort is a brutal way to stop a thread, but sometimes necessary. However, it doesn't clean things up all that well, which may be the cause of the program getting slower and slower.
As to using a background thread, that's harder to say. Normally, that would be the exactly right thing to do in this case...more or less. Using a BackGroundWorker would allow you to update the UI on the UI thread (ReportProgress event), but it looks like that is ALL your background thread is doing aside from sleeping. The big question is whether the actual code takes noticeable time. If it does, then you DO have to use a thread. If the actual code in updateUIfunc is really fast, then a thread isn't the way to go. Just use a timer with an interval of 200 and do the work in the tick event.
My usual boring signature: Nothing
-
Feb 13th, 2021, 05:55 AM
#6
Thread Starter
New Member
Re: Aborting a thread running an infinite loop
Originally Posted by Shaggy Hiker
The first thing I would try is just removing the abort. It would be a good experiment.
300ms would be a third of a second delay (roughly). That would be a noticeable stutter, but just barely. If you see something more than that, there may be something else going on. Abort is a brutal way to stop a thread, but sometimes necessary. However, it doesn't clean things up all that well, which may be the cause of the program getting slower and slower.
By doing this, you are saying that just with the bool running = False the thread will die?
That is the correct way to stop the thread, at the same time cleaning the things up properly?
As to using a background thread, that's harder to say. Normally, that would be the exactly right thing to do in this case...more or less. Using a BackGroundWorker would allow you to update the UI on the UI thread (ReportProgress event), but it looks like that is ALL your background thread is doing aside from sleeping. The big question is whether the actual code takes noticeable time. If it does, then you DO have to use a thread. If the actual code in updateUIfunc is really fast, then a thread isn't the way to go. Just use a timer with an interval of 200 and do the work in the tick event.
The experiment that i'm using right now, is instead of sleeping for 200 ms, i have a timer inside the thread that upon the timer it calls the update function.
Would you recomend something similar?
I'm still calling the abort method followed by join.
Code:
Public updateUIAutoThread As New System.Threading.Thread(AddressOf DoStuff)
Private thread_cycle As Integer = 100
Private Sub Page_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
updateUIAutoThread.IsBackground = False
running = True
running2 = True
If Not updateUIAutoThread.IsAlive Then
updateUIAutoThread.Start()
End If
End Sub
Private Sub Page_Unloaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Unloaded
updateUIAutoThread.Abort()
updateUIAutoThread.Join()
end sub
Private Delegate Sub DoStuffDelegate()
Private updateUI2 As DoStuffDelegate = AddressOf updateUI
Public Sub TimerCallback(ByVal seder As Object, ByVal e As System.Timers.ElapsedEventArgs)
Try
Me.Dispatcher.Invoke(updateUI2)
Catch ex As ThreadAbortException
Thread.ResetAbort()
Catch ex As Exception
MessageBox.Show("Erro thread AUTOMATIC cycle:" & vbCrLf & ex.ToString)
End Try
End Sub
Private Sub DoStuff()
Dim t As New System.Timers.Timer(thread_cycle)
AddHandler t.Elapsed, AddressOf TimerCallback
t.AutoReset = True
t.Enabled = True
End Sub
-
Feb 13th, 2021, 10:55 AM
#7
Re: Aborting a thread running an infinite loop
Did you ever try the whole thing on the UI thread without using a background thread? I'm curious as to what you found if you did. If you didn't, then that might be something to try.
Normally, the kind of thing you are doing (communicating with a different device) would make sense in a background thread, so you may have just realized that and started out that way, which would be understandable. I'm pretty sure that I would have started out that way, too. However, that background thread isn't really DOING anything. It just passes work off to the UI thread every now and then.
For that reason, I'd be inclined to scrap the thread entirely and see how it worked. Use a Forms.Timer, and just call the update in the tick event. That may be wrong, though. In the code you originally posted, there is nothing that should take more than a fraction of a millisecond....except, possibly, this line (and those like it):
intVariables("readingPressureCaixao1").reading
That could be a very simple lookup that is virtually instantaneous, or it could do some kind of communication that is slower. I don't know, but you do. If that line is essentially instant, then there doesn't appear to be any need for a thread at all, because all you are doing could be done in the UI thread on the timer tick without the program slowing down any. On the other hand, if that does some kind of reading which takes any measurable amount of time, then a thread does make sense, but not necessarily the way you are using it. You'd want to do the reading in the thread, but possibly not update the controls as part of the thread.
It all comes down to whether there is anything that takes any noticeable time. Currently, there doesn't appear to be, in which case the use of a thread will probably slightly slow your program overall.
My usual boring signature: Nothing
-
Feb 25th, 2021, 03:56 AM
#8
Thread Starter
New Member
Re: Aborting a thread running an infinite loop
I manage to reduce the problem to the amount of data that i was passing to the ui thread to update.
Imagine that i have a frame within a page, both the main page and the page inside the frame runs on the same thread?
Or individual threads are created? I have the feeling that they both run on the same ui thread.
-
Feb 25th, 2021, 10:30 AM
#9
Re: Aborting a thread running an infinite loop
They run on the same UI thread unless you tell them otherwise, and that's usually the way you want it.
My usual boring signature: Nothing
-
Feb 25th, 2021, 11:22 AM
#10
Thread Starter
New Member
Re: Aborting a thread running an infinite loop
Can you please tell me how can i do that? Or point me in the right direction. I really need to have them running on separate threads ...
-
Feb 25th, 2021, 12:04 PM
#11
Re: Aborting a thread running an infinite loop
Something just dawned on me: Is this a web application or WPF?
My usual boring signature: Nothing
-
Feb 25th, 2021, 12:24 PM
#12
Thread Starter
New Member
Re: Aborting a thread running an infinite loop
It's WPF, but it's running on an embedded computer and the performance it's not what i expected. That's why I'm working on not always give new update commands.
But why did that question arrived?
I just want to have as many ui threads as i can, so that the ui is a responsive as possible.
If you can give me some help on making the frame run on a different thread it would be very helpful.
-
Feb 25th, 2021, 12:34 PM
#13
Re: Aborting a thread running an infinite loop
Moderator action: Moved to WPF forum.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|