Reputation: 141
I am attempting to update the progress bar on a main form with the work being done in a different class. For example:
private void transfer_Click(object sender, EventArgs e)
{
Guid aspnetUserId = Guid.Parse(System.Configuration.ConfigurationSettings.AppSettings["ASPNetUserID"]);
WC1toWC2Transfer transfer = new WC1toWC2Transfer(aspnetUserId);
backgroundWorker1.RunWorkerAsync(transfer);
}
And then in the background method actually call the method:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
WC1toWC2Transfer transfer = e.Argument as WC1toWC2Transfer;
transfer.WC1ToWC2EmployerTransfer(log, wc1ConnStr, wc2ConnStr, progressBar1);
}
In the WC1ToWC2EmployerTransfer method, I'm setting the progress bar maximum and updating the value everytime something is transferred to the database in this method, but when I do this nothing happens. There's code inside the method that runs a stored procedure in a database, but as soon as it hits that portion of the code, it stops debugging and I have to run the process again.
Am I doing something wrong here? Do I need to rewrite what I have so the actual methods are in the main form and not in a different class? I'm a junior developer (just started a few months ago) so forgive me if I'm doing something blatantly wrong or if I didn't explain this well enough.
Any help would be greatly appreciated.
Upvotes: 2
Views: 6397
Reputation: 6465
I think the reason is that you get an IllegalCrossThreadException
, because you're attempting to access the control from a different thread than it was created. The BackgroundWorker
provides a ReportProgress method and a ProgressChanged event that is typically used for such updating and which will be executed on the UI thread. When accessing the progressbar from another thread than the UI thread, do it like this:
if(progressBar1.InvokeRequired) {
progressBar1.Invoke(new MethodInvoker(delegate { progressBar1.Maximum = someValue; }));
}
As a sidenote: It's not very good design to pass the progressbar to your worker class. The form could close, it could get disposed and the worker would not know anything about it, eventually failing with an ObjectDisposedException
that probably isn't caught. Additionally, you're making the worker dependent on System.Windows.Forms
when it probably doesn't need to. Rather let your worker report progress through an event and pass that on to your progressbar from the class that created the worker.
Upvotes: 1
Reputation: 931
You cant alter the UI unless you are on the main thread, which you BackgroundWorker will not be.
What you need to do is create an event handler in the main form to handle the backgroundworker's ProgressChanged event.
eg
// this method should be in your main form.
private void backgroundworker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// update your progress bar here.
}
In your background worker, you call the ReportProgress method which will fire the ProgressChanged event.
There is a nice example here.
Upvotes: 2