Results 1 to 13 of 13

Thread: Aborting a thread running an infinite loop

  1. #1

    Thread Starter
    New Member
    Join Date
    Feb 2021
    Posts
    6

    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
    Name:  2.jpg
Views: 274
Size:  31.0 KB

    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.

  2. #2
    Wall Poster TysonLPrice's Avatar
    Join Date
    Sep 2002
    Location
    Columbus, Ohio
    Posts
    3,518

    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!

  3. #3
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    35,928

    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

  4. #4

    Thread Starter
    New Member
    Join Date
    Feb 2021
    Posts
    6

    Re: Aborting a thread running an infinite loop

    Quote Originally Posted by Shaggy Hiker View Post
    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

  5. #5
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    35,928

    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

  6. #6

    Thread Starter
    New Member
    Join Date
    Feb 2021
    Posts
    6

    Re: Aborting a thread running an infinite loop

    Quote Originally Posted by Shaggy Hiker View Post
    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

  7. #7
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    35,928

    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

  8. #8

    Thread Starter
    New Member
    Join Date
    Feb 2021
    Posts
    6

    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.

  9. #9
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    35,928

    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

  10. #10

    Thread Starter
    New Member
    Join Date
    Feb 2021
    Posts
    6

    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 ...

  11. #11
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    35,928

    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

  12. #12

    Thread Starter
    New Member
    Join Date
    Feb 2021
    Posts
    6

    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.

  13. #13
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    10,120

    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
  •  



Click Here to Expand Forum to Full Width