I'm working on an application that has a main form with a status bar at the bottom. The status bar contains a ProgressBar, and a Label that I want to use to show the user the current progress of some work that is being done. The status bar also contains a label which I want to use like a click-able Cancel button.

I've create asynchronous interfaces before like this, but they have always been based around a single action, and by using a background worker. But in this new program there are a number of different actions the user may envoke all of which I want to use this same status bar to show the progress of. So I'm trying to figure out a way to generalize and standardize the interface to these progress reporting controls in the status bar.

In some cases the asynchronous processes are created using a BackGroundWorker, yet in other cases I need to create an manage the secondary threads directly.

Here's some half finished skeleton code of what I've been thinking:

```
public partial class MyForm: System.Windows.Forms.Form
{
    ...SNIP...

    private void WorkProgressChanged(Object sender, EventArgs args)
    {
        ProgressChangedEventArgs backgroundWorkerArgs = args as ProgressChangedEventArgs;
        ProgressReport formReport = args as ProgressReport; //my own custom progress report class

       //tries to cast args to a Background worker args
        if (backgroundWorkerArgs != null)
        {
            // update UI based on backgroundWorkerArgs

        }
        else if (formReport != null)
        {
            // update UI basd on formReport

        }

        else 
        {
            //couldn't figure out what kind of progress report was sent
            //update UI based on args.ToString();

        }

    }

    private void cancelButtonToolStripLabel_Click(object sender, EventArgs e)
    {
        //calls cancel method of current processing
        if (this._currentWorkCancelAction != null)
        {
            _currentWorkCancelAction(); //envoke cancel requet
            cancelButtonToolStripLabel.Text = "Canceling"; //shows user that cancel request was made
            _currentWorkCancelAction = null; //disaccociates cancel button to prevent user from canceling twice
        }
    }

    private void WorkProcessCompleted(Object sender, EventArgs args)
    { 
        //Reset cancel button
        cancelButtonToolStripLabel.Text = "Cancel";
        cancelButtonToolStripLabel.Visible = false;

        //resets the status label and progress bar
        statusToolStripLabel.Text = "";
        toolStripProgressBar.Value = 0;

    }

....SNIP

}

```

So the status bar is updated by subscribing `WorkProgressChanged(Object sender, EventArgs args) to some event
', and ultimately reset when 'WorkProcessCompleted(Object sender, EventArgs args)' is envoked by a completion even. My cancel label (button) also needs to be associated and later dissociated with a delegate method that will request that whatever work is currently being done is canceled.

So each time work is done a bunch of stuff needs to happen. Event subscriptions are added/remove, delegate references are changed etc.. etc.. So I started wondering if there was some way I could encapsulate all these actions in to one or two reusable methods rather then writing duplicate code for each action that may take place. 

The `InitWorkProcess()` method below shows how I am thinking this may work . Although I'm pretty sure this is not the right way to use the EventDescriptor class. I couldn't figure out any other way to reference an event as a method parameter. Maybe this isn't possible?

```
    public void InitWorkProcess(EventDescriptor workProgressChangedEvent, EventDescriptor workCompletedEvent, System.Action requestCancel)
    { 
        //subscribe to progress changed
        workProgressChangedEvent.AddEventHandler(this, this.WorkProgressChanged);
        this._workProgressChangedEvent = workProgressChangedEvent;

        //subscribe to process completed
        workCompletedEvent.AddEventHandler(this, this.WorkProcessCompleted);
        this._workCompletedEvent = workCompletedEvent;

        //enable cancel button
        if (requestCancel != null)
        {
            cancelButtonToolStripLabel.Visible = true;
            this._currentWorkCancelAction = requestCancel;
        }
    }

```

... and I'd change the WorkProgressComplete event handling method to unsubscribe the event relationships when the work is completed.

```
    private void WorkProcessCompleted(Object sender, EventArgs args)
    { 
        //Reset cancel button
        cancelButtonToolStripLabel.Text = "Cancel";
        cancelButtonToolStripLabel.Visible = false;

        //resets the status label and progress bar
        statusToolStripLabel.Text = "";
        toolStripProgressBar.Value = 0;

        //unsubscribes WorkProcessCompleted() and WorkProgressChanged() methods
        this._workCompletedEvent.RemoveEventHandler(this, this._workCompletedEvent);
        this._workCompletedEvent = null;

        this._workProgressChangedEvent.RemoveEventHandler(this, this._workProgressChangedEvent);
        this._workProgressChangedEvent = null;
    }

```

Does anyone have any suggestions on how I should set this up? Should I just forget about the `InitWorkProcess()` method and instead add/remove all the event/delegate relationships separately for each action? Or is there a better way entirely?