2010-03-30 139 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

相关问题