Using BackgroundWorker with ProgressBar in WPF
Hi i have an App where one of the jobs will be convert an Excel and pass all the records to the DB.
So this takes a little time because it's more than 7000 rows that i will get and insert into the DB.
So because this job takes a little time, more than 3 minutes, I'd like to use a ProgressBar to report progress of this job.
So if i am doing this Job in Class that i have created, how can i use the backgroundWorker to report the progress to the progessBar in my case?
My objective is be accurate in the percentage of how the progress is going, and how i can use all this stuff to report 开发者_开发技巧the progress. I have never worked with backgroundWorkers.
I think, and this is only a tip, maybe good or not, that i first get the number of rows in the excel, make that number as some Maxvalue in the ProgressBar, and then for each Row or in an interval i report the progress.
This is possible? How can i do it?
I like to use bindings for ProgressBars (and pretty much everything else where possible) because that way you do not need to worry about dispatching to the UI thread.
Basically you create some class that implements INotifyPropertyChanged with a progress property that you can bind your ProgressBar to. e.g.
public class Task : INotifyPropertyChanged
{
private int _progress = 0;
public int Progress
{
get { return _progress; }
private set
{
if (_progress != value)
{
_progress = value;
OnPropertyChanged("Progress");
}
}
}
public Task(ref ProgressChangedEventHandler progressChangedEvent)
{
progressChangedEvent += (s, e) => Progress = e.ProgressPercentage;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
This class uses an event in the constructor which will update the Task's progress if raised but you can handle the Progress change in any way you like, e.g. a method or by making the Progress property public
so you can just change it arbitrarily.
Usage example:
<ProgressBar Minimum="0" Maximum="100" Height="20"
Value="{Binding UpdateTask.Progress, Mode=OneWay}"/>
// The event that should be raised when a progress occurs.
private event ProgressChangedEventHandler UpdateProgressChanged;
// The task the ProgressBar binds to.
private readonly Task _updateTask;
public Task UpdateTask
{
get { return _updateTask; }
}
public MainWindow()
{
// Instatiate task, hooking it up to the update event.
_updateTask = new Task(ref UpdateProgressChanged);
}
private void OnUpdateProgressChanged(int progressPercentage)
{
if (UpdateProgressChanged != null)
{
UpdateProgressChanged(this, new ProgressChangedEventArgs(progressPercentage, null));
}
}
// Simple progress simulation
private void Button1_Click(object sender, RoutedEventArgs e)
{
int progress = 0;
DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(0.5) };
timer.Tick += (sSub,eSub) =>
{
progress++;
// Raise progress changed event which in turn will change
// the progress of the task which in turn will cause
// the binding to update which in turn causes the value
// of the ProgressBar to change.
OnUpdateProgressChanged(progress);
if (progress == 100)
{
timer.Stop();
}
};
timer.Start();
}
Here's an example of a background worker with progress.
However, double-check to make sure a BGW will work in your situation. If you're controlling Excel via COM interop, it may require an STA thread (and a BGW is an MTA thread, not STA).
If that's the case, you'll need to use a Task
with an STA scheduler, or your own manual Thread
(I strongly suggest the Task
-based approach).
精彩评论