Question GUI Thread slow to update - background worker related

Cheetah

Well-known member
Joined
Oct 12, 2006
Messages
232
Programming Experience
Beginner
Hi there,

I have a progress bar which shows the progress from a background worker.

On backgroundworker.progresschanged event I have it update the progress bar (adding 1 to the value), and change the text of a label (in that order).

But it seems that the progress bar is lagging, as the text updates straight away, but it takes about a second before the progressbar indicates the change (if that makes sense).

Anyone else get this issue? Do you know if it can be fixed?

Thanks.
 
No answer as to why it happens but I was able to reproduce it.

Using the code below the listbox fills to Sequence #10 before I see the progress bar move which would be the 1 second you're seeing.

The sequence list finishes about the same time interval before the progress bar stops moving also.

VB.NET:
    Private Sub bgw_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
        Dim ListText As String
        For Value As Integer = 0 To 100
            If bgw.CancellationPending Then
                Exit For
            End If
            ListText = String.Concat("Sequence #", Value)
            bgw.ReportProgress(Value, ListText)
            Threading.Thread.Sleep(100)
        Next
        Dim ds As New DataSet
        ds = e.Result
    End Sub

    Private Sub bgw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgw.ProgressChanged
        ProgressBar1.Value = e.ProgressPercentage
        ListBox1.Items.Add(e.UserState)
        ListBox1.SelectedIndex = ListBox1.Items.Count - 1
    End Sub
 
Glad it's not just me :p

Can I ask though, why did you put the threading.sleep on the background worker? I am guessing it was so the GUI thread would not lock because the background worker thread is using all the CPU cycles?
 
Can I ask though, why did you put the threading.sleep on the background worker? I am guessing it was so the GUI thread would not lock because the background worker thread is using all the CPU cycles?

Just an artificial delay so I could see how far behind the listbox updating the progress bar was.
 
I'm not able to reproduce the mentioned issue, here progressbar changes at value 1, then at varying values depending on the bar width and the value of Step property (defaults 10). Also seems to stop around same time. Tried in both VB2005 and 2008, same.
 
I'm not able to reproduce the mentioned issue, here progressbar changes at value 1, then at varying values depending on the bar width and the value of Step property (defaults 10).

That is making me think a bit, and I am wondering, it could be do to with the fact that I have the step set to 1 and the maximum is variably set and just incremented by one each time.

If i had the maximum set to 100 and i just manually set the value property each time i want to change it, it does exactly the same thing.
 
I didn't do anything but drop a ListBox and ProgressBar onto the page so both have default values.

I'm getting the same behavior on both my Vista and XP boxes. VS2005 on both of them.

(Forum won't let me attach a swf file so you'll need to dig into the archive to get it.)
 

Attachments

  • bgw.zip
    112.6 KB · Views: 12
That is making me think a bit, and I am wondering, it could be do to with the fact that I have the step set to 1 and the maximum is variably set and just incremented by one each time.

If i had the maximum set to 100 and i just manually set the value property each time i want to change it, it does exactly the same thing.
I think that is not a good approach. Max 100 is reliably always true for percentage. There are many situations, for example common file operations where file sizes are measured as Long, where the max value is too large to fit the Integer type of the progressbar property. You already have the value and max, so calculating percent from this is simply (value*100\max) and you can leave the controls max as is.
 
But it seems that the progress bar is lagging, as the text updates straight away, but it takes about a second before the progressbar indicates the change (if that makes sense).

You have the progressbar style set to BLOCKS
Set it to continuous instead
 
I didn't do anything but drop a ListBox and ProgressBar onto the page so both have default values.

I'm getting the same behavior on both my Vista and XP boxes. VS2005 on both of them.

(Forum won't let me attach a swf file so you'll need to dig into the archive to get it.)

Including the project might have been helpful.. ? ps; there's no way that your movie is a shot of you sleeping 100ms every loop
 
Yeah, I changed the sleep to make the video size smaller. Here's the full code behind I'm using.

Dropped a progressbar and listbox on the form with no changes and renamed 2 buttons to btnStart and btnCancel.

VB.NET:
Imports System.ComponentModel

Public Class Form1

    Private WithEvents bgw As BackgroundWorker = New BackgroundWorker

    Private Sub bgw_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
        Dim ListText As String
        For Value As Integer = 0 To 100
            If bgw.CancellationPending Then
                Exit For
            End If
            ListText = String.Concat("Sequence #", Value)
            bgw.ReportProgress(Value, ListText)
            Threading.Thread.Sleep(5)
        Next
        Dim ds As New DataSet
        ds = e.Result
    End Sub

    Private Sub bgw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgw.ProgressChanged
        ProgressBar1.Value = e.ProgressPercentage
        ListBox1.Items.Add(e.UserState)
        ListBox1.SelectedIndex = ListBox1.Items.Count - 1
    End Sub

    Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
        btnStart.Enabled = False
        btnCancel.Enabled = True
        ListBox1.Items.Clear()
        ProgressBar1.Value = 0
        bgw.WorkerReportsProgress = True
        bgw.WorkerSupportsCancellation = True
        bgw.RunWorkerAsync()
        Me.Cursor = Cursors.WaitCursor
    End Sub

    Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
        bgw.CancelAsync()
        Me.Cursor = Cursors.Arrow
    End Sub

    Private Sub bgw_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgw.RunWorkerCompleted
        btnStart.Enabled = True
        btnCancel.Enabled = False
        Me.Cursor = Cursors.Arrow
    End Sub
End Class
 
You have the progressbar style set to BLOCKS
Set it to continuous instead

I understand why you have said that, because I would have said the same thing, but the progress bar is already set to continuous.

My problem is the same issue as MattP videoed.

Been doing some googling and apparently this is a known issue when the value of the progress bar changes quickly, another example of when this problem would occur would be downloading a file and showing how much had downloaded through the progress bar, as the amount of bytes that have downloaded would change very quickly, it would cause the lag. - But this is the issue that confused me, my progressbar value doesn't actually change that quickly (probably once every 2-5 seconds at most)

Apparently (from what i have read), and i am not too sure on this, the solution is to create your own control for the progress bar, but i fail too see why this would be any different.
 
Last edited:
Back
Top