Modo corretto per smaltire un BackGroundWorker

Questo sarebbe un modo corretto di disporre di un BackGroundWorker? Non sono sicuro che sia necessario rimuovere gli eventi prima di chiamare .Dispose (). Chiama anche .Dispose () all’interno del delegato RunWorkerCompleted, ok?

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 deriva da Component. Componente implementa l’interfaccia IDisposable. Ciò a sua volta fa in modo che BackgroundWorker erediti il ​​metodo Dispose ().

Derivando da Component è una comodità per i programmatori di Windows Form, possono rilasciare un BGW dalla casella degli strumenti su un modulo. I componenti in genere hanno una certa probabilità di avere qualcosa da smaltire. Il progettista di Windows Form si occupa automaticamente di questo, cerca nel file Designer.cs un modulo per il campo “componenti”. Il suo metodo Dispose () generato automaticamente chiama il metodo Dispose () per tutti i componenti.

Tuttavia, BackgroundWorker non ha effettivamente alcun membro che richieda lo smaltimento. Non sovrascrive Dispose (). La sua implementazione di base, Component.Dispose (), fa in modo che il componente venga rimosso dalla raccolta “components”. E solleva l’evento Disposed. Ma non disponga altrimenti nulla.

Per farla breve: se hai lasciato una BGW su un modulo, allora tutto è gestito automaticamente, non devi aiutare. Se non lo hai lasciato su un modulo, allora non è un elemento in una raccolta di componenti e non è necessario fare nulla.

Non è necessario chiamare Dispose () .

Verso la fine del gioco, ma mi sono imbattuto in uno scenario relativo alla tua domanda che pensavo di condividere. Se si crea il lavoratore a livello di class e lo si riutilizza nelle operazioni successive senza chiudere l’app, se non si rimuovono gli eventi dopo il completamento, questi verranno incrementati ed eseguiti più volte in ogni esecuzione successiva.

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

Senza il precedente il mio DoWork spara una volta, due volte la seconda, ecc. Questo è probabilmente un gioco da ragazzi per la maggior parte, ma mi ci è voluto un po ‘per capirlo, quindi spero che questo possa aiutare qualcun altro.

worker.Dispose() non è richiesto, poiché Dispose() viene chiamato automaticamente. Ma prima di smaltire l’object è necessario rimuovere tutti i gestori di eventi.

Questo articolo ci informa su questo.

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

Sì, questo sembra corretto. Ovviamente, gli oggetti usa e getta sono meglio gestiti con l’ using blocchi, ma qui non hai questa opzione.

Generalmente creo i miei handler di sfondo con le forms di vita, li riuso e lascia che il codice del designer gestisca lo smaltimento in base alla forma. Meno da pensare.

Se si trova su un modulo “WinForms”, lascia che sia il contenitore a occuparsene (vedi il codice Dispose generato nel file Form.Designer.xyz)

In pratica ho scoperto che potrebbe essere necessario creare un’istanza del contenitore e aggiungere il lavoratore (o altro utente) ad esso, se qualcuno conosce un modo più ufficiale per farlo urlare !!

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