Yoav
Yoav

Reputation: 2077

Backgroundworker subscribing to events

I have a form. The form has a logic class that does something. I want the form to be responsive while this something is done so I create a BackgroundWorker object. I also want to get updates from the logic class to the form. I thought to use the progress update event of the BackgroundWorker.

So I subscribe a method on the form to to worker.ProgressChanged.

public class MyForm : Form
{
    private LogicClass logicObject;

    public void StartOperation()
    {
        BGWorkerBase worker = new BGWorkerBase(logicObject);
        worker.DoWork += new DoWorkEventHandler(DoOperation);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(OperationComplete);
        worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
        worker.RunWorkerAsync();
    }

    public void DoOperation()
    {
        logicObject.DoSomething();
    }

    private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // Update form
    }
}

I created a custome Backgroundworker which subscribes to the update event of the logic class and invokes the ProgressChanged event:

public class BGWorkerBase : BackgroundWorker
{
    public BGWorkerBase(LogicClass logicObject)
    {
        // connection is the logic class. it has an update event
        logicObject.UpdatePublished += new EventHandler(connection_UpdatePublished);
        this.WorkerReportsProgress = true;
    }
    // Here I invoke the backgroundworker OnProgressChangedEvent
    private void connection_UpdatePublished(object sender, EventArgs e)
    {
        OnProgressChanged(new ProgressChangedEventArgs(0, e));
    }
}

The problem is that as I trigger the operation repeatedly, the update is being published multiple times. I checked and found that the connection object has multiple workers subscribed to the publish event. So it seems I created 2 problems here:
1. A single event is published multiple times. 2. I am keeping a reference in the connection object to backgroundworkers which should have been disposed of once they finished their job.

What would be the best way to fix this? I may be able to remove the subscription of the worker when its completing its job, but it seems dirty. Is there a better way to manage this situation?

Upvotes: 2

Views: 1660

Answers (1)

Jakob Christensen
Jakob Christensen

Reputation: 14956

You should unsubscribe from the event when the worker has finished. I.e. somewhere in your code you should add the following:

logicObject.UpdatePublished -= connection_UpdatePublished;

This will remove your event handler from the list of delegates registered to handle the UpdatePublished event.

This SO question/answer explains how you may accidentally create memory leaks using events: Why and How to avoid Event Handler memory leaks?

Upvotes: 4

Related Questions