ProgressBar is slow in Windows Forms

This is just how the Vista/7 progress bar is designed. When you change the value of the progress bar, the bar is animated to that value progressively.

The only way I know of avoiding this problem is to go backwards when updating the progress bar, as follows:

progressBar1.Value = n;
if (n>0)
    progressBar1.Value = n-1;

For a more complete discussion see Disabling .NET progressbar animation when changing value?


You can easily write a custom progress bar to show its value without animation. The following is a simple implementation to show the progress from 0 to 100 and revert to 0.

public class ProgressBarDirectRender : UserControl
{
    private int _value;
    public int Value
    {
        get { return _value; }
        set
        {
            if (value < 0 || value > 100)
                throw new ArgumentOutOfRangeException("value");
            _value = value;
            const int margin = 1;
            using (var g = CreateGraphics())
            {
                if (_value == 0)
                    ProgressBarRenderer.DrawHorizontalBar(g, ClientRectangle);
                else
                {
                    var rectangle = new Rectangle(ClientRectangle.X + margin,
                                                  ClientRectangle.Y + margin,
                                                  ClientRectangle.Width * _value / 100 - margin * 2,
                                                  ClientRectangle.Height - margin * 2);
                    ProgressBarRenderer.DrawHorizontalChunks(g, rectangle);
                }
            }
        }
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        ProgressBarRenderer.DrawHorizontalBar(e.Graphics, ClientRectangle);
    }
}

Building off of Heffernan's tip on going backwards with the progress bar and Reinhart's extension method approach in a related question, I came up with my own solution.

The solution is pretty seamless and successfully handles the issue you will encounter when the value is at Maximum. This extension method to ProgressBar alleviates the lagging that is caused from the progressive animation style present in the WinForms ProgressBar control when running on Windows Vista and 7 (I haven't tested on Windows 8 yet).

public static class ExtensionMethods
{
    /// <summary>
    /// Sets the progress bar value, without using 'Windows Aero' animation.
    /// This is to work around a known WinForms issue where the progress bar 
    /// is slow to update. 
    /// </summary>
    public static void SetProgressNoAnimation(this ProgressBar pb, int value)
    {
        // To get around the progressive animation, we need to move the 
        // progress bar backwards.
        if (value == pb.Maximum)
        {
            // Special case as value can't be set greater than Maximum.
            pb.Maximum = value + 1;     // Temporarily Increase Maximum
            pb.Value = value + 1;       // Move past
            pb.Maximum = value;         // Reset maximum
        }
        else
        {
            pb.Value = value + 1;       // Move past
        }
        pb.Value = value;               // Move to correct value
    }
}

Sample usage:

private void backgroundWorker_ProgressChanged(object sender, 
                                                  ProgressChangedEventArgs e)
{
     progressBar.SetProgressNoAnimation(e.ProgressPercentage);
}

Tags:

C#

.Net

Winforms