I want to refresh a progess bar in C# WPF.
This question sounds very easy and i should be able to google it. But the solutions I have seen unsatisfy me.
Assuming that i have to run a very long algorithm with e.g. 5 different steps. I don't know exactly how long it will take to calculate the different steps. But i know what i have programmed an i could use a profiler to check how much time the CPU uses for each step (in % of the total time for all steps).
This could be the times e.g.:
Method1() takes 3s
Method2() takes 5s
Method3() takes 1s
This are my approaches:
The "Easy" Approach:
ProgressBar pb = new ProgressBar()
{
// The total duration of all methods
Maximum = 9
};
Method1();
// + 3 for 3 seconds
pb.Value += TimeForMethod1;
Method2();
// + 5 for 5 seconds
pb.Value += TimeForMethod2;
Method3();
// + 1 for 1 second
pb.Value += TimeForMethod3;
This is pretty easy. But has a problem. This blocks my UI thread for 9 seconds wich is horrible (because the user could think the programm has crashed).
So it seems obvious to use a thread..
The "Thread" Approach:
This has the problem that I need to dispach every operation on the ProgressBar which could be very slow (for very much updates on the ProgressBar)
I have written a "TaskQueue" for that. I can save all work I want to do in a Queue
and a Thread
is working all these Task after Run
is called and updates the ProgressBar
(and a Label
) between the Tasks.
I don't want to post all the code of the ThreadQueue
, because it is very much and maybe not that good implemented (yet).
This is the important part of the thread method:
foreach (var threadQueueNode in threadQueue)
{
// Changes e.g. a label displaying what the thread is doing next
threadQueueNode.PreMainFunction.Invoke();
// Executes the main task
this.Result = threadQueueNode.MainFunction.Invoke();
// Updates the ProgressBar after the work is done.
threadQueueNode.PostMainFunction.Invoke();
}
PostMainFunction is a Delegate
and e.g. this:
PostMainFunction = (Action<int>)((value) => this.Dispatcher.Invoke(() => this.ProgressBarStatus.Value += value));
Wich is the professional way to update a ProgessBar for a problem like mine?
I'd be happy about a discussion.
Thanks for your help and your time!
BackgroundWorker is clean and legible: