Is it possible to hide the ProgressChanged event in a backgroundworker class?
I have created a class that inherits System.ComponentModel.BackgroundWorker and I need to have multiple events: My class processes a list of objects and I need (for example) to have events before and after an object is processed. I fire those events from the Backgroundworker's ProgressChanged event, because it is thread safe. The method in my class that is called when I invoke ReportProgress then uses the parameter to determine which event to fire. That works.
Now I want to make sure, that the class calling my Backgroundworker is not allowed to subscribe to the ProgressChanged event directly. Instead it should only be possible to subscribe to the additional events that I provide.
There are a few approaches:
Disallow subscription and suppress firing
The subclass can be written to (a) throw an exception if a caller attempts to subscribe directly to the ProcessChange event, and (b) not raise the event at all. Note that (a) alone does not prevent the event from being subscribed to, since callers can cast the subclass as a BackgroundWorker and subscribe to the event directly:
class ExtendedBackgroundWorker : BackgroundWorker
{
public new event ProgressChangedEventHandler ProgressChanges
{
add { throw new InvalidOperationException("This event cannot be added directly"); }
remove {}
}
protected override void OnProgressChanged(ProgressChangedEventArgs e)
{
// do not call base.OnProgressChanged
}
}
Use composition in place of inheritance
If possible, however, a better approach may be to not inherit from BackgroundWorker at all. A BackgroundWorker uses the ProgressChanged event to report progress changes; if it does not do so, it is not a BackgroundWorker. Instead, consider implementing the BackgroundWorker as a private class member and exposing members from the member as needed, e.g.:
class CustomBackgroundWorker : Component
{
private BackgroundWorker worker;
public event ProgressChangedEventHandler FirstEvent;
public event ProgressChangedEventHandler SecondEvent;
public event DoWorkEventHandler DoWork
{
add { worker.DoWork += value; }
remove { worker.DoWork -= value; }
}
public event RunWorkerCompletedEventHandler RunWorkerCompleted
{
add { worker.RunWorkerCompleted += value; }
remove { worker.RunWorkerCompleted -= value; }
}
public CustomBackgroundWorker()
{
worker = new BackgroundWorker();
worker.ProgressChanged += OnProgressChanged;
worker.WorkerReportsProgress = true;
}
public void RunWorkerAsync()
{
worker.RunWorkerAsync();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
worker.Dispose();
}
private void OnProgressChanged(object o, ProgressChangedEventArgs e)
{
// code to handle progress change reports from the worker
}
}
Refire event to be of use to client
Rather than suppressing use of the event, the subclass can use it in conjunction with (rather than as a substitute for) the other events to provide relevant information to the subscriber (e.g., the progress of the total operation).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With