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);
}