Results 1 to 6 of 6

Thread: [RESOLVED] Thread Is Too Fast

  1. #1

    Thread Starter
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,146

    Resolved [RESOLVED] Thread Is Too Fast

    I have to run off somewhere, and I haven't had enough time to think about this issue, so I thought I'd toss out a problem in search of a better solution. It's a good problem to have, too.

    I wrote a program back around 2003/2005 that...had a LOT of iterations, each of which took a stately amount of time. The result was that the program would take roughly 1.5 days to run to completion. Just recently, I decided to dust off that project and bring it into the modern age. Computers are faster these days, there are more cores, and the program is an example of an embarrassingly parallel application. It REALLY could benefit from threading on multiple cores. No thread will be waiting for any length of time, so threading on a single core never made sense, but threading on multiple cores makes LOTS of sense.

    So, I got it working, and have found that it runs too fast. Not a bad problem to have, really, but it messes with the interface. The program is a genetic algorithm. It goes through many thousands of generations in a run. Previously, it went fast enough that it looked pretty good, but the user would be able to use some tools to visualize the evolution over time. Now, it's just too fast, so I'm considering how to change the interface such that the user can still visualize things.

    One piece of that is that I need a means to pause a thread. The main loop is running in a BackGroundWorker. My first thought is that I could run that loop inside a sync block. The first step of the loop could be to lock an object, which would then be released at the end of the loop. Of course, this would mean that the lock would be reacquired almost immediately, but there would be an instruction or two during which it would be released. If some of the UI actions wanted to pause the loop, they could also lock that object. This seems like it would work. So long as the UI element held the lock, the BGW would not be able to loop. Once the UI element released the lock, the loop would continue.

    Is there any issue with that approach, and is there any other approach I ought to consider to temporarily suspend a thread?
    My usual boring signature: Nothing

  2. #2
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,801

    Re: Thread Is Too Fast

    If it runs super quick, i.e. like in the blink of an eye, then you can simply store what it does in an array. Then once it finishes, replay the array at a stepped interval using a BackgroundWorker like you suggested. Keep in mind that you probably don't have to do it every time too. You could replay it on command, e.g. a user clicks a "replay build" button that simulates the visualization at a slower pace and even lets them step through it if they want.

    That is entirely up to how you think the users would actually use the application. This could be great or it could wind up being a feature that exists, nobody uses, but is all of a sudden required on future rewrites.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  3. #3
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    539

    Re: Thread Is Too Fast

    How about defining a ManualResetEvent object that the backgroundworker checks periodically:

    Code:
    Imports System.Threading
    
    Public Class Form1
    
    
        Private resetEvent As New ManualResetEvent(False)
        Private backgroundThread As Thread
        Private backgroundThreadStarted As Boolean = False
    
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            backgroundThread = New Thread(AddressOf BackgroundWorker)
        End Sub
    
    
        Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
            If backgroundThread IsNot Nothing AndAlso backgroundThread.IsAlive Then
                backgroundThread.Abort()
            End If
        End Sub
    
    
        Private Sub StartButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartButton.Click
            If Not backgroundThreadStarted Then
                ' Start the background thread
                backgroundThread.Start()
                resetEvent.Set()
                backgroundThreadStarted = True
            Else
                MessageBox.Show("Background worker is already running.")
            End If
        End Sub
    
    
        Private Sub PauseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PauseButton.Click
            If backgroundThreadStarted Then
                ' Reset the ManualResetEvent, pausing the background thread
                resetEvent.Reset()
            Else
                MessageBox.Show("Background worker is not running.")
            End If
        End Sub
    
    
        Private Sub ResumeButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ResumeButton.Click
            If backgroundThreadStarted Then
                ' Set the ManualResetEvent, allowing the background thread to resume
                resetEvent.Set()
            Else
                MessageBox.Show("Background worker is not running.")
            End If
        End Sub
    
    
        Private Sub BackgroundWorker()
            Try
                While True
                    ' Check if the ManualResetEvent is signaled (set)
                    resetEvent.WaitOne()
    
                    ' Perform background work here
                    Console.WriteLine("Background work in progress...")
    
                    ' Simulate some work
                    Thread.Sleep(1000) ' Sleep for 1 second
                End While
            Catch ex As ThreadAbortException
                ' Handle thread abort gracefully
            End Try
        End Sub
    
    
    End Class

  4. #4

    Thread Starter
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,146

    Re: Thread Is Too Fast

    The UI that people will mostly be looking at was a "Hollywood" interface that I added after a presentation. It doesn't DO anything useful. It just shows colored lines bouncing around on the screen to visualize the progress of the evolution towards a goal. Replaying that would be possible, and could certainly be of some slight interest, but since it's ultimately useless, I think it would be a feature nobody would use. The real time display was only so that I could have it running in the background for presentations. The other part that would be good to pause for, makes no sense to see in replay. In fact, I had forgotten that it existed, but now that I see it, I see how useful it would be, but not on replay.

    @Peter: That's probably simpler than what I was thinking of, so I'll give it a try. It should be able to do what I want pretty easily.
    My usual boring signature: Nothing

  5. #5

    Thread Starter
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,146

    Re: Thread Is Too Fast

    Looks like the ManualResetEvent works as I want it to, and I feel it is somewhat better suited to the task than the locking object I was thinking of using.
    My usual boring signature: Nothing

  6. #6
    Fanatic Member Peter Porter's Avatar
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    539

    Re: [RESOLVED] Thread Is Too Fast

    Glad it works for you, Shaggy.

    Just for anyone who finds this thread, here's the same code again, but using a BackgroundWorker with ManualResetEvent:

    Code:
    Imports System.Threading
    
    
    Public Class Form1
    
    
        Private resetEvent As New ManualResetEvent(False)
        Private backgroundWorker As New System.ComponentModel.BackgroundWorker()
        Private isPaused As Boolean = False
    
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            ' Register event handlers for the BackgroundWorker
            AddHandler backgroundWorker.DoWork, AddressOf BackgroundWorker_DoWork
            AddHandler backgroundWorker.ProgressChanged, AddressOf BackgroundWorker_ProgressChanged
    
            ' Enable progress reporting
            backgroundWorker.WorkerReportsProgress = True
        End Sub
    
    
        Private Sub StartButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartButton.Click
            If Not backgroundWorker.IsBusy Then
                ' Start the background worker
                backgroundWorker.RunWorkerAsync()
                resetEvent.Set()
            Else
                If isPaused Then
                    MessageBox.Show("Background worker is already running, but paused.")
                Else
                    MessageBox.Show("Background worker is already running.")
                End If
            End If
        End Sub
    
    
        Private Sub PauseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PauseButton.Click
            ' Pause the background worker by resetting the ManualResetEvent
            resetEvent.Reset()
            Label1.Text = "Background worker is paused."
            isPaused = True
        End Sub
    
    
        Private Sub ResumeButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ResumeButton.Click
            ' Resume the background worker by setting the ManualResetEvent
            resetEvent.Set()
            isPaused = False
        End Sub
    
    
        Private Sub BackgroundWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
            Dim worker As System.ComponentModel.BackgroundWorker = CType(sender, System.ComponentModel.BackgroundWorker)
    
            While Not worker.CancellationPending
                ' Check if the ManualResetEvent is signaled (set)
                resetEvent.WaitOne()
    
                ' Perform background work here
                Console.WriteLine("Background work in progress...")
    
                ' Report progress
                worker.ReportProgress(0, "Background work in progress...")
    
                ' Simulate some work
                Thread.Sleep(1000) ' Sleep for 1 second
            End While
        End Sub
    
    
        Private Sub BackgroundWorker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs)
            ' Update UI with progress information
            Label1.Text = e.UserState.ToString()
        End Sub
    
    
    End Class
    It needs 3 Button controls "StartButton, PauseButton, ResumeButton," and one Label control.

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