2010-03-30 113 views
45

這是處理BackGroundWorker的正確方法嗎?我不確定在調用.Dispose()之前是否需要刪除事件。另外調用RunWorkerCompleted委託內的.Dispose()可以嗎?處理BackGroundWorker的正確方法

public void RunProcessAsync(DateTime dumpDate) 
{ 
    BackgroundWorker worker = new BackgroundWorker(); 
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); 
    worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
    worker.RunWorkerAsync(dumpDate); 
} 

void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    // Do Work here 
} 

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    BackgroundWorker worker = sender as BackgroundWorker; 
    worker.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); 
    worker.DoWork -= new DoWorkEventHandler(worker_DoWork); 
    worker.Dispose(); 
} 
+0

這是一個窗體上的後臺工作? – 2010-03-30 01:38:05

+0

是的,儘管我以編程方式創建了BGW,而不是將它放在設計器的窗體中。如圖所示,當我想運行線程時,BGW被創建。這個想法是每次調用線程時創建一個不同的BGW,並在完成時處理它們。 – galford13x 2010-03-30 21:31:36

回答

67

BackgroundWorker派生自Component。組件實現了IDisposable接口。這反過來使BackgroundWorker繼承Dispose()方法。

派生自Component對於Windows Forms程序員來說很方便,他們可以將BGW從工具箱拖放到表單上。一般來說,組件可能有些東西需要處理。 Windows窗體設計器會自動處理此問題,請在Designer.cs文件中查找「組件」字段的窗體。其自動生成的Dispose()方法爲所有組件調用Dispose()方法。

但是,BackgroundWorker實際上並沒有任何需要處理的成員。它不重寫Dispose()。其基本實現Component.Dispose()僅確保將組件從「組件」集合中刪除。並提出Disposed事件。但沒有其他處置任何東西。

長話短說:如果您在表單上放置了BGW,那麼所有內容都會自動處理,您不必提供幫助。如果您沒有將它放在表單上,​​那麼它不是組件集合中的元素,也不需要做任何事情。

您不必調用Dispose()

+6

就我個人而言,如果在課程實施實際發生變化的情況下,我確實喜歡遵循調用「Dispose」的策略...... – 2010-03-30 02:04:15

+3

我不能與此爭論。但是更願意總是這樣想:「一個需要處置的類可以包裝什麼樣的對象?」看看。我無法編寫沒有意義的代碼,也不會購買這樣的概念,即某一天它會有意義。它也可以用其他方式工作:Thread類實際上具有一次性對象,但不實現IDisposable。給他自己。 – 2010-03-30 02:18:12

+1

就這麼理解。 BGW不需要處置,因爲它沒有任何可處置的東西。我曾經讀過一段時間,如果事件沒有被刪除,當一個依賴它們的對象被處置時,它們可以繼續掛出以防止釋放資源。這是不是這種情況? – galford13x 2010-03-30 19:24:17

0

是的,這似乎是正確的。當然,一次性物品最好用using塊處理,但您在這裏沒有該選項。

我通常用表單生命週期創建我的背景handers,重用它們,並讓設計器代碼在窗體關閉時處理處理。少想一想。

+0

這就是我過去一直這樣做的方式。雖然我沒有意識到在設計時將BackGroundWorker拖放到WinForm上,但將BGW添加到表單處理時將要放置的對象列表中。我通常以編程方式創建了BGW。 – galford13x 2010-03-30 19:21:07

0

如果它是一個「的WinForms」形式讓容器照顧它(查看生成的代碼Dispose在Form.Designer.xyz文件)

在實踐中我發現,你可能需要創建一個如果有人知道一個更正式的方式來做到這一點,那麼容器的實例並添加工人(或其他companent)到它!

PK :-)

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 

     // watch the disposed event.... 
     backgroundWorker1.Disposed += new EventHandler(backgroundWorker1_Disposed); 

     // try with and without the following lines 
     components = new Container(); 
     components.Add(backgroundWorker1); 
    } 

    void backgroundWorker1_Disposed(object sender, EventArgs e) 
    { 
     Debug.WriteLine("backgroundWorker1_Disposed"); 
    } 

//... from the Designer.xyz file ... 

    /// <summary> 
    /// Clean up any resources being used. 
    /// </summary> 
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
    protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

} 
13

晚了比賽,但我只是碰到與你的問題,我想我會分享一個場景跑去。如果您在課堂級別創建工作人員並在不關閉應用程序的情況下在連續的操作中重複使用它,如果您未在完成後移除事件,則它們將在每次後續執行時遞增並運行多次。

worker.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); 
worker.DoWork -= new DoWorkEventHandler(worker_DoWork); 

沒有上面我DoWork的閃光一次,第一次,兩次,第二次,等等。這可能是一個沒有腦子的大多數,但我花了一點的數字出來,所以希望這將幫助別人。

+0

您能否提供您的方案的更詳細的代碼。我使用BW和這(據我所知)從來沒有發生過我 – 2012-08-14 12:58:37

+0

沒有寫一個完整的例子沒有更多的解釋,但我會嘗試。如果「worker」在使用它的方法之外定義(即全局在應用程序級別),但是您在其中一個方法中訂閱了該工作人員,而不必在每次迭代中刪除該訂閱,那麼訂閱將繼續呈指數增長。 – Paul 2012-08-14 13:31:41

+0

我的理解是,您正在多次調用的方法中訂閱事件。如果是這樣的話:是的,當然;如果不是,我仍然不明白。 – 2012-08-14 13:54:39

1

worker.Dispose()不是必需的,因爲Dispose()被自動調用。但在處理對象之前,您需要刪除所有事件處理程序。

這個article通知我們這件事。

worker.RunWorkerCompleted -= new RunWorkerCompletedEventHandle(worker_RunWorkerCompleted); 
worker.DoWork -= new DoWorkEventHandler(worker_DoWork); 
+1

如果以前的文章提到刪除事件處理程序時,它不再是如此。在鏈接文章的所有版本中,都沒有提到事件。 – kbrimington 2015-02-11 04:36:27