Question

I'm performing some tests with an scrollbar in Winforms. I have the following code, that seems to be correct, but I never see the scrollbar completely fill. When the scrollbar value reaches 100, the scroll draw is as shown in this picture (about 50%).

enter image description here

This is the example code that I'm using:

    private void animate_scroll(object sender, EventArgs e)
    {
        progressBar1.Minimum = 0;
        progressBar1.Maximum = 100;
        progressBar1.Step = 1;

        ThreadPool.QueueUserWorkItem(new WaitCallback(AnimateScroll));
    }

    private void AnimateScroll(object state)
    {
        while (true)
        {
            mValue = (mValue + 1) % 101;
            this.Invoke((MethodInvoker)delegate()
            {
                progressBar1.Value = mValue;
                System.Diagnostics.Debug.WriteLine(progressBar1.Value);
            });
            System.Threading.Thread.Sleep(10);
        }
    }

    private int mValue = 0;
Was it helpful?

Solution

According to the following David Heffernan's answer, the issue is caused by the animation added in Windows 7. The issue gets fixed doing the following trick:

                progressBar1.Value = mValue;
                progressBar1.Value = mValue - 1;

OTHER TIPS

This is happening because there is animation built into the WinForms ProgressBar control. To see this for yourself, just change your animate_scroll method like so:

    private void animate_scroll(object sender, EventArgs e)
    {
        progressBar1.Minimum = 0;
        progressBar1.Maximum = 100;
        progressBar1.Step = 1;
        // ThreadPool.QueueUserWorkItem(new WaitCallback(AnimateScroll));

        // here's the change:
        progressBar1.Value = 100;
    }

As you'll see, when you programmatically change the value from 0 (the default) to 100, the ProgressBar control animates itself to expand its content to the width that corresponds to the value. Your original code is sending Value updates faster than the control can animate between the values.

There doesn't seem to be a way to change the way this animation works. Maybe your use case would be satisfied just by setting the Style property to Marquee, which scrolls a highlighted section across the control.

I am doing the same type of thing to test my progress bar before the actual function gets implemented. I estimated my final function will take around 5 seconds to complete, so I set up the progress bar to have a maximum of 100 and a step of 1. Then I created a loop to 100 and did a Thread.Sleep(50) each loop for about 5 seconds of time.

for( int ii = 0; ii < 110; ++ii)
{
    Thread.Sleep(50);
    form.statusOutputMainChannel(ii.ToString());
    form.progressBarVerifyUpdate();
}

I found that I had to call the bar.PerformStep() method another 10 times in order for the animation to catch up to the value.

This is another "ugly" way to get it to work, but it's not clear to me that the other answers really got to a "this fixes it" either.

  • Rob

Try this. It works for me.

If ProgressBar1.Value = ProgressBar1.Maximum Then
    wait(500)
    ProgressBar1.Value = ProgressBar1.Maximum
End If

And the Wait sub is:

Public Sub wait(ByVal interval As Integer)
    ' Loops for a specificied period of time (milliseconds)
    Dim sw As New Stopwatch
    sw.Start()
    Do While sw.ElapsedMilliseconds < interval
        ' Allows UI to remain responsive
        Application.DoEvents()
    Loop
    sw.Stop()
End Sub

C# answer: Create a method to finish and update the progress bar:

public async Task<bool> DoProgressbarFinishStep()
{
    myProgress.progressBar1.Value = myProgress.progressBar1.Maximum;
    await Task.Delay(5000);
    return true;
}

then when your other routine is finished doing its loop, call the method:

bool result = await DoProgressbarFinishStep();

The ProgressBar control will then update correctly to 100% during those 5000 milliseconds (or whatever time works for you).

From what I can tell, the ProgressBar appears to exhibit this behaviour on purpose, and needs asynchronous programming to work well. Let's face it, if you are performing such a long task that it requires a progress bar, then you should be programming asynchronously anyway to avoid locking up UI threads.

Read more (2021) at https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top