C#:我是否需要处理在运行时创建的BackgroundWorker?

Ric*_*ckL 32 c# dispose backgroundworker

我通常在表单上有这样的代码:

    private void PerformLongRunningOperation()
    {
        BackgroundWorker worker = new BackgroundWorker();

        worker.DoWork += delegate
        {
            // perform long running operation here
        };

        worker.RunWorkerAsync();
    }
Run Code Online (Sandbox Code Playgroud)

这意味着我不会处理它BackgroundWorker,而如果我已经由表单设计者添加它,那么我认为它会被处理掉.

这会导致任何问题吗?声明模块级别_saveWorker,然后Dispose从表单的dispose方法调用它更正确吗?

Sim*_*ens 32

是的,你应该处理后台工作人员.

您可能会发现它更容易使用ThreadPool.QueueUserWorkItem(...),之后不需要任何清理.


有关为何应始终调用Dispose()的其他详细信息:

虽然如果查看BackgroundWorker类,它实际上并没有在它的dispose方法中进行任何线程清理,但由于该类对垃圾收集器的影响,调用Dispose仍然很重要.

具有终结器的类不会立即进行GC.它们被保留并添加到终结器队列中.然后运行终结器线程(遵循标准模式调用dispose).这意味着该对象将继续存在于GC生成1中.而第1代集合远比gen 0集合更少,因此您可以在内存中反复使用更长时间.

但是,如果您调用Dispose(),则该对象将不会添加到终结队列中,因此可以自由地进行垃圾回收.

这不是什么大问题,但是如果你创造了很多它们,你最终会使用比必要更多的内存.始终在具有dispose方法的对象上调用dispose应该被认为是一种好习惯.

所以我想,总而言之,这不是100%的硬性和快速要求.如果您不调用Dispose(),您的应用程序将不会爆炸(甚至泄漏内存),但在某些情况下,它可能会产生负面影响.后台工作程序设计为可以作为WinForms组件使用,所以如果你有不同的要求并且不想将它用作WinForms组件,请不要使用它,使用正确的工具,像ThreadPool一样.

  • _为什么他应该调用bgw.Dispose()?除了通常的'因为它有'逻辑'. (8认同)

Nei*_*ell 16

挑战在于确保只BackgroundWorker 完成运行后才处理掉.您无法在Completed事件中执行此操作,因为该事件由BackgroundWorker本身引发.

BackgroundWorker真的打算用作WinForms表单上的一个组件,所以我建议你这样做,或者切换到类似的东西Thread.QueueUserWorkItem.这将使用线程池线程,并且在完成时不需要任何特殊清理.

  • +1对于"BackgroundWorker"旨在用作WinForms组件. (4认同)

les*_*ode 7

在我看来,一般来说,如果它是IDisposable,那么当你完成它时它应该是Dispose()d.即使在技术上不需要处理BackgroundWorker的当前实现,您也不希望后来的内部实现感到惊讶.


Hen*_*man 6

我不会打扰,Bgw可以保留的唯一资源是Thread,如果你的代表中没有无限循环那么你很好.

BackgroundWorker继承IDisposable()自Component,但并不真正需要它.

将它与直接在ThreadPool上推送方法进行比较.你没有(不能)Dispose线程,当然不是来自Pool的线程.

但是如果你的样本是完整的,你没有使用Completed事件或Progress/Cancel功能,你也可以使用ThreadPool.QueueUserWorkItem().

  • 线程对象非常昂贵(至少它们包含大量的保留堆栈内存,可能是1MB). (2认同)