Background worker Argument and Result
Because the background worker runs in a different thread, it cannot interact easily with the main UI thread.
It is good to keep in mind:
* The DoWork method is in it's own thread.
* The RunWorkerCompleted method is in the main UI thread.
Passing into and out of the background worker is simple.
When you start the worker, you can easily add an object as such:
try
{
bgWorker.RunWorkerAsync(myObject);
}
catch (Exception ex)
{
throw;
}
In the backgound worker method you get the object as the routed event argument 'Argument'.
Pass something back thru the 'Result' arguement.
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
MyObject myObject= e.Argument as MyObject;
// do something
// Put the result in e.Result
e.Result = myNewObject;
}
You can get the result in the RunWorkerCompleted method:
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MyObject myNewObject = e.Result;
// do something else
}
It is all very simple.
You can also loop thru an object in the RunWorkerCompleted method and have the results display as they finish:
int counter = myObjectList.Count();
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MyObject myNewObject = e.Result;
if (myNewObject != null)
{
UpdateTheUI(myNewObject);
System.Windows.Forms.Application.DoEvents(); // forces a UI update
}
if (counter < myObjectList.Count())
{
MyObject o = myObjectList[counter];
bgWorker.RunWorkerAsync(o);
counter++;
}
else
{
bgWorker.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
bgWorker.DoWork -= new DoWorkEventHandler(bgWorker_DoWork);
}
}
Background workers
Background workers are VERY useful. They keep you to do run intensive process without locking up your UI.
Again, a picture (or code) is worth a thousand words...
// Declare your background worker
private BackgroundWorker bgWorker = new BackgroundWorker();
// In the constructor or some other method you must initialize things
private void StartBackgroundWorker()
{
// When the background worker finishes, this event is triggered
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
// When the background worker is started, this event is triggered
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
// If the background worker is canceled, this event is triggered
bgWorker.WorkerSupportsCancellation = true;
// Create a button someplace to stop the background worker
btnStop.Click += new RoutedEventHandler(btnStop_Clicked);
// start the background worker
try
{
bgWorker.RunWorkerAsync();
}
catch (Exception ex) { // do something }
}
private void btnStop_Clicked(object sender, RoutedEventArgs e)
{
// Unregister the events or they may not get garbage collected
btnStop.Click -= new RoutedEventHandler(btnStop_Clicked);
bgWorker.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
bgWorker.DoWork -= new DoWorkEventHandler(bgWorker_DoWork);
// stop the background worker
bgWorker.CancelAsync();
}
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Start the process
// This will be done in a seperate thread
}
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
return;
}
if (e.Error != null)
{
return;
}
// show the user the results of the process that was running... or whatever you want to do
// Unregister the events or they may not get garbage collected
btnStop.Click -= new RoutedEventHandler(btnStop_Clicked);
bgWorker.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
bgWorker.DoWork -= new DoWorkEventHandler(bgWorker_DoWork);
}
That is all there is to it! Simple? Sure it is.
However, there are some things you should know.
* If you cancel the background worker, they process is not stopped. It will continue running until it finishes. Canceling simple disconnects that thread and stops listening to it.
* If you want to stop that thread, then you should have that thread often check for the cancel event and stop itself if it is TRUE.
* If you start and cancel a process too many time, you can will ecounter problems. You should develope a way to prevent this.