views:

75

answers:

2

I know that this could look a dumb question, but here's my problem. I have a worker dialog that "hides" a backgroundworker, so in a worker thread I do my job, I report the progress in a standard way and then I show the results in my WPF program. The dialog contains a simply animated gif and a standard wpf progress bar, and when a progress is notified I set Value property. All lokks as usual and works well for any kind of job, like web service calls, db queries, background elaboration and so on. For my job we use also many "couplers", card readers that reads data from smart card, that are managed with native C code that access to serial port (so, I don't use .NET SerialPort object). I have some nunit tests and I read a sample card in 10 seconds, but using my actual program, under the backgroundworker and showing my worker dialog, I need 1.30 minutes to do the SAME job. I struggled into problem for days until I decide to remove the worker dialog, and without dialog I obtain the same performances of the tests! So I investigated, and It's not the dialog, not the animated gif, but the wpf progress bar! Simply the fact that a progress bar is shown (so, no animation, no Value set called, nothing of nothing) slows serialport communicatitons. Looks incredible? I've tested this behavior and it's exactly what happens.

+1  A: 

What you describe sounds completely normal. Updating a progress bar's value once is a relatively trivial task, but if your code is performing a large number of operations, then updating the progress bar each time can end up taking much more total time than just the operations would themselves.

If your code performs, say, 10,000 operations, try setting your progress bar's maximimum value to 10, and only update the bar every 1,000 operations.

Another possibility is to set the bar's value using BeginInvoke instead of Invoke (if this is how you're doing it in the first place). Invoke blocks until the invoked method is completed, which means each operation in your loop has to wait for the progress bar to be updated before continuing.

MusiGenesis
I update progressbar only few times, and only the fact that the progressbar is shown (no value set called) slows performances.
D_Guidi
actual code I've used was: var duration = new Duration(TimeSpan.FromSeconds(0.25)); ar animation = new DoubleAnimation(percentage, duration); this.progressBar.BeginAnimation(RangeBase.ValueProperty, animation);but I've tried also calling set_Value property directly and let progressbar without calling setter, experiency the same poor performances
D_Guidi
after a litte bit of verification, let the progressbar without calling setter don't slows performances, sorry for the mistake.
D_Guidi
A: 

I always use the following code for updating progress bars (has to be run in the UI thread)

private int UpdateCount = 0;

public void UpdateProgress(int value)
{
 // We are updating every tenth time.
 if (((UpdateCount % 10) == 0)) {
  ProgressBar1.Value = value;
 }

 UpdateCount += 1;
}
Rick Ratayczak
Or even better, use Rx :) `progressObservable.Throttle(TimeSpam.FromMilliseconds(250)).Subscribe(x => ProgressBar1.Value = x);`
Richard Szalay
Richard, sounds elegant, but where would I find the progressObservable class?
Rick Ratayczak
I could try with Rx, maybe the performances remains poor, but what a style of code :D
D_Guidi