La forma correcta de deshacerse de un BackGroundWorker

¿Esta sería una forma adecuada de deshacerse de un BackGroundWorker? No estoy seguro de si es necesario eliminar los eventos antes de llamar a .Dispose (). También está llamando .Dispose () dentro del delegado RunWorkerCompleted para hacer?

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 se deriva de Component. El componente implementa la interfaz IDisposable. Eso a su vez hace que BackgroundWorker herede el método Dispose ().

Derivar de Component es una conveniencia para los progtwigdores de Windows Forms, pueden colocar un BGW de la caja de herramientas en un formulario. Es probable que los componentes en general tengan algo que desechar. El diseñador de Windows Forms se ocupa de esto automáticamente, busque en el archivo Designer.cs un Formulario para el campo “componentes”. Su método Dispose () generado automáticamente llama al método Dispose () para todos los componentes.

Sin embargo, BackgroundWorker en realidad no tiene ningún miembro que requiera deshacerse. No anula Dispose (). Su implementación base, Component.Dispose (), solo se asegura de que el componente se elimine de la colección de “componentes”. Y levanta el evento Disposed. Pero de otro modo no dispone de nada.

Para resumir, si eliminaste un BGW en un formulario, entonces todo se soluciona automáticamente, no tienes que ayudar. Si no lo colocó en un formulario, entonces no es un elemento en una colección de componentes y no es necesario hacer nada.

No tiene que llamar a Dispose () .

Tarde en el juego, pero me encontré con un escenario relacionado con tu pregunta que pensé que compartiría. Si crea su trabajador en el nivel de clase y lo reutiliza en operaciones sucesivas sin cerrar la aplicación, si no elimina los eventos después de la finalización, se incrementarán y ejecutarán varias veces en cada ejecución sucesiva.

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

Sin lo anterior, mi DoWork se dispara una vez la primera vez, el doble de la segunda vez, etc. Probablemente esto sea obvio para la mayoría, pero me llevó un poco averiguarlo, así que con suerte esto ayudará a alguien más.

worker.Dispose() no es obligatorio porque se llama automáticamente a Dispose() . Pero antes de eliminar el objeto, debe eliminar todos los controladores de eventos.

Este artículo nos informa sobre esto.

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

Sí, esto parece correcto. Por supuesto, los objetos desechables se manejan mejor con el using bloques, pero no tienes esa opción aquí.

Por lo general, creo mis ejecuciones de segundo plano con vidas útiles, las vuelvo a usar, y dejo que el código del diseñador maneje la eliminación en forma cercana. Menos para pensar.

Si está en un Formulario “WinForms”, deje que el contenedor se encargue de ello (consulte el código Dispose generado en el archivo Form.Designer.xyz)

En la práctica, he descubierto que puede necesitar crear una instancia del contenedor y agregarle el trabajador (u otra compañía), si alguien conoce una forma más oficial de gritar.

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 ... ///  /// Clean up any resources being used. ///  /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } }