Reputation: 153
I am executing a DLL using backgroundWorker1
which updates a variable i
by reference. To update a progress bar using i
, I use the following code. I also want to show the percentage as text. The problem is that the text (NOT the progress bar) flickers a lot. How can I reduce/remove this flicker? Increasing sleep duration is not an option.
BackgroundWorker backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += (s, args) =>
{
Mydll.MyCFunction(ref i);
};
backgroundWorker1.RunWorkerAsync();
while (backgroundWorker1.IsBusy)
{
backgroundWorker1.ReportProgress(i * 100);
backgroundWorker1.ProgressChanged += (s, e) =>
{
progressBar1.Refresh();
progressBar1.Value = e.ProgressPercentage;
progressBar1.CreateGraphics().DrawString(e.ProgressPercentage.ToString() + "%",
SystemFonts.DefaultFont, Brushes.Black,
new PointF(progressBar1.Width / 2 - 10, progressBar1.Height / 2 - 7));
};
Application.DoEvents();
System.Threading.Thread.Sleep(200);
}
Thanks.
Upvotes: 0
Views: 3045
Reputation: 426
If graphics flicker you should enable double buffering.
DoubleBuffered = true
Or
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
For more information: http://msdn.microsoft.com/en-us/library/3t7htc9c.aspx
Upvotes: 1
Reputation: 14618
Firstly, I'd remove the line Application.DoEvents();
(excellent post on do events), this is usually indicative of bad multithreaded design. I'd also remove the Thread.Sleep
call personally as well.
Secondly, you should be subscribing to ProgressChanged
OUTSIDE of the worker loop. For example:
public Form1()
{
bgWorker.ProgressChanged += bgWorker_ProgressChanged;
}
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
progressBar1.CreateGraphics().DrawString(e.ProgressPercentage.ToString() + "%",
SystemFonts.DefaultFont, Brushes.Black,
new PointF(progressBar1.Width / 2 - 10, progressBar1.Height / 2 - 7));
}
Upvotes: 0
Reputation: 77304
Your code has multiple bugs. One of them, generally speaking is calling Application.DoEvents
. That may have been useful in VB6 15 years ago, but that's technology stone age. You are also attaching the same handler to the event multiple times, which means after 100 loops your drawing will be called 100 times per percent.
With so much wrong it's hard to suggest a simple fix. Have a look here for two simple ways to make this work. Try to understand what happends, in which order and why.
Upvotes: 0
Reputation: 309
Your code will be subscribing to the ProgressChanged event many, many times over. You should only need to subscribe one event to it. Having all these events will mean that for every progress changed, an increasing number of refreshes on the progress bar will occur.
I'd suggest creating a separate event handler for the progress changed event and making sure you only subscribe once.
So, trying to keep your design:
Subscribe event handler to ProgressChanged (Event Handler declared elsewhere)
Loop {
ReportProgress
DoEvents
Sleep }
As a side note, why are you sleeping the thread?
Upvotes: 1