2013-01-14 111 views
2

我有一個表單。該表單有一個邏輯類來執行某些操作。我希望表單能夠在響應時完成,因此我創建了一個BackgroundWorker對象。 我也想從邏輯類更新到窗體。我想使用BackgroundWorker的進度更新事件。

所以我訂閱了一個表單上的方法到worker.ProgressChanged。
訂閱事件的Backgroundworker

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 
    } 
} 

我創建的是定製的BackgroundWorker其訂閱的邏輯類的更新事件,並調用ProgressChanged事件:

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)); 
    } 
} 

的問題是,作爲本人重複觸發操作中,更新是多次出版。我檢查並發現連接對象有多個訂閱了發佈事件的工作者。所以看來我在這裏創建了兩個問題:
1.單個事件多次發佈。 2.我在連接對象中保留一個對背景工作者的引用,這些背景工作者在完成他們的工作之後應該已經處理掉了。

什麼是解決這個問題的最好方法?我可以在完成工作時刪除工作人員的訂閱,但看起來很髒。有沒有更好的方法來管理這種情況?

回答

4

工作完成後,您應該取消訂閱活動。即地方在你的代碼,你應該添加以下內容:

logicObject.UpdatePublished -= connection_UpdatePublished; 

這會從註冊到處理UpdatePublished事件委託列表中刪除你的事件處理程序。

這個SO提問/回答解釋瞭如何可能會不小心使用事件導致內存泄漏: Why and How to avoid Event Handler memory leaks?