简体   繁体   English

处理BackGroundWorker的正确方法

[英]Proper way to Dispose of a BackGroundWorker

Would this be a proper way to dispose of a BackGroundWorker? 这是处理BackGroundWorker的正确方法吗? I'm not sure if it is necesary to remove the events before calling .Dispose(). 我不确定在调用.Dispose()之前是否需要删除事件。 Also is calling .Dispose() inside the RunWorkerCompleted delegate ok to do? 还在RunWorkerCompleted委托中调用.Dispose()确定吗?

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

BackgroundWorker derives from Component. BackgroundWorker派生自Component。 Component implements the IDisposable interface. Component实现了IDisposable接口。 That in turn makes BackgroundWorker inherit the Dispose() method. 这反过来使BackgroundWorker继承Dispose()方法。

Deriving from Component is a convenience for Windows Forms programmers, they can drop a BGW from the toolbox onto a form. 从Component派生是Windows Forms程序员的便利,他们可以将BGW从工具箱中删除到表单上。 Components in general are somewhat likely to have something to dispose. 一般来说,组件可能有某些东西需要处理。 The Windows Forms designer takes care of this automatically, look in the Designer.cs file for a Form for the "components" field. Windows窗体设计器自动处理此问题,在Designer.cs文件中查找“components”字段的Form。 Its auto-generated Dispose() method calls the Dispose() method for all components. 它的自动生成的Dispose()方法为所有组件调用Dispose()方法。

However, BackgroundWorker doesn't actually have any member that requires disposing. 但是,BackgroundWorker实际上没有任何需要处理的成员。 It doesn't override Dispose(). 它不会覆盖Dispose()。 Its base implementation, Component.Dispose(), only makes sure that the component is removed from the "components" collection. 它的基本实现Component.Dispose()只确保从“components”集合中删除该组件。 And raise the Disposed event. 并提出Disposed事件。 But doesn't otherwise dispose anything. 但是没有其他任何处理。

Long story short: if you dropped a BGW on a form then everything is taken care of automatically, you don't have to help. 长话短说:如果你在表格上放弃一个BGW,那么一切都会自动处理,你无需帮助。 If you didn't drop it on a form then it isn't an element in a components collection and nothing needs to be done. 如果你没有将它放在表单上,​​那么它不是组件集合中的元素,也不需要做任何事情。

You don't have to call Dispose() . 您不必调用Dispose()

Late to the game, but I just ran across a scenario related to your question that I thought I would share. 在游戏的后期,但我刚遇到了与我的问题相关的情景,我认为我会分享。 If you create your worker at the class level and reuse it on successive operations without closing the app, if you don't remove the events after completion they will increment and run multiple times on each successive execution. 如果您在类级别创建工作程序并在不关闭应用程序的情况下在连续操作上重复使用它,如果在完成后不删除事件,则它们将在每次连续执行时递增并运行多次。

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

Without the above my DoWork fires once the first time, twice the second time, etc. This is probably a no-brainer for most, but it took me a bit to figure it out, so hopefully this will help someone else out. 没有上面我的DoWork第一次发射,第二次发射两次,等等。对于大多数人来说,这可能是一个明智的选择,但是我花了一些时间来解决它,所以希望这会帮助其他人。

worker.Dispose() is not required, because Dispose() is automatically called. worker.Dispose()不是必需的,因为会自动调用Dispose() But before disposing the object you need to remove all events handlers. 但在处置对象之前,您需要删除所有事件处理程序。

This article informs us about this. 本文向我们介绍了这一点。

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

Yes, this appears proper. 是的,这似乎是正确的。 Of course, disposable objects are better handled with using blocks, but you don't have that option here. 当然, using块可以更好地处理一次性对象,但是这里没有这个选项。

I usually create my background handers with form lifetimes, reuse them, and let the designer code handle disposal on form close. 我通常使用表单生命周期创建我的后台处理程序,重用它们,并让设计器代码处理表单上的处理。 Less to think about. 少考虑一下。

If it's on a "WinForms" Form let the container take care of it (see the generated Dispose code in the Form.Designer.xyz file) 如果它在“WinForms”表单上让容器处理它(请参阅Form.Designer.xyz文件中生成的Dispose代码)

In practice I have found that you may need to create an instance of the container and add the worker (or other companent) to it, if anyone knows a more official way to do this yell out!! 在实践中,我发现你可能需要创建一个容器的实例并将工作者(或其他组件)添加到它,如果有人知道更正式的方法来做到这一点!

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM