In the final post of the three part series, we are going to finish up or BackgroundMethod class. In Part 1, we covered the basics of the class. In Part 2, we started building the core of our class. In this final part, we are going to handle three things: the DoWork event, the RunWorkerCompleted event, and Unhooking our event subscriptions.
Okay, lets start with the DoWork event. What we want here is to grab our entry delegate and invoke it, passing a parameter to it if necessary.
void DoWorkHandler(object sender, DoWorkEventArgs e)
{
try
{
object[] parameters = null;
if (_parameter != null)
{
parameters = new object[] { _parameter };
}
e.Result = _entryDelegate.Method.Invoke(_entryDelegate.Target, parameters);
}
catch (Exception ex)
{
e.Result = ex;
}
BackgroundWorker worker = sender as BackgroundWorker;
e.Cancel = worker.CancellationPending;
}
So, like we said before, create the parameters, and call invoke. In the event args, we are going to pass our result, if we get one. As well, if we throw an exception we will set the result of the work to the exception. Finally, we grab the background worker, check if somebody has set the work to be cancelled, and set Cancel to true if need be. In the handler for work completed, we are going to use this result to complete the processing if necessary.
void RunWorkerCompletedHandler(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
_errorAction(e.Error);
}
else if (!e.Cancelled && e.Error == null)
{
if (e.Result is Exception)
{
_errorAction(e.Result as Exception);
}
else
{
if (_callbackDelegate != null)
{
object[] parameters = null;
if (e.Result != null)
{
parameters = new object[] { _parameter };
}
_callbackDelegate.Method.Invoke(_callbackDelegate.Target, parameters);
}
}
}
Dispose();
}
First, check for an error. Our error action is finally coming into play here for the exception. This way, if the background method didn’t work for some reason, pass the exception back up to the main thread so we can log it or handle it gracefully. If there was no error and the background worker hasn’t been cancelled, check for the result as an exception, calling the error action again if so.
Finally, if our method ran okay, we are going to check for a callback delegate. As previously stated, we are covering the most complex scenario in which we have a callback delegate. In more simple scenarios, you may not want to do anything we the method is completed. Here we do, so we are going to create a set or parameters, and if the DoWork handler gave us a value (our entry method could return void), we call invoke on the callback delegate.
Last, and certainly not least, we are going to call Dispose. In the dispose method somewhere, we will call this method.
void UnhookBackgroundWorker(BackgroundWorker bw)
{
if (bw.IsBusy)
{
bw.CancelAsync();
}
bw.DoWork -= DoWorkHandler;
bw.RunWorkerCompleted -= RunWorkerCompletedHandler;
bw.Dispose();
bw = null;
}
Just some cleanup here. Unhook the methods, call dispose on the background worker. And that’s it! We now have a fully reusable class that is fairly simple to use. You can find an example of the usage attached here, as well as the full BackgroundMethod class.
Talk soon.
1 comments:
This is an interesting series. Unfortunately the link forthe zip file is not functioning.
Will the file be available?
Post a Comment