Bonne façon de disposer D'un BackGroundWorker

Serait-ce une bonne façon de disposer D'un BackGroundWorker? Je ne suis pas sûr s'il est nécessaire de supprimer les événements avant d'appeler .Disposer(). Également de l'appelant .Dispose() dans le délégué RunWorkerCompleted ok à faire?

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();
}
46
demandé sur galford13x 2010-03-30 05:36:09

5 réponses

BackgroundWorker dérive du composant. Le composant implémente L'interface IDisposable. Cela fait que BackgroundWorker hérite de la méthode Dispose ().

Dériver du composant est une commodité pour les programmeurs Windows Forms, ils peuvent déposer un BGW de la boîte à outils sur un formulaire. Les composants en général sont quelque peu susceptibles d'avoir quelque chose à éliminer. Le Concepteur Windows Forms prend soin de cela automatiquement, regardez dans le concepteur.fichier cs pour un formulaire pour les " composants" champ. Sa méthode Dispose () générée automatiquement appelle la méthode Dispose () pour tous les composants.

Cependant, BackgroundWorker n'a pas de membre nécessitant une disposition. Il ne remplace pas Dispose (). Sa mise en œuvre de base, composante.Dispose(), s'assure uniquement que le composant est supprimé de la collection" components". Et augmenter l'événement disposé. Mais ne dispose pas autrement quoi que ce soit.

Longue histoire courte: si vous avez laissé tomber un BGW sur un formulaire alors tout est pris en charge automatiquement, vous n'avez pas à aider. Si vous ne l'avez pas déposé sur un formulaire, ce n'est pas un élément dans une collection de composants et rien ne doit être fait.

Vous n'avez pas besoin D'appeler Dispose().

68
répondu Hans Passant 2010-03-30 01:53:57

En retard au jeu, mais je viens de croiser un scénario lié à votre question que je pensais partager. Si vous créez votre worker au niveau de la classe et le réutilisez lors d'opérations successives sans fermer l'application, si vous ne supprimez pas les événements après l'achèvement, ils s'incrémentent et s'exécutent plusieurs fois à chaque exécution successive.

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

Sans ce qui précède, mon DoWork se déclenche une fois la première fois, deux fois la deuxième fois, etc. C'est probablement une évidence pour la plupart, mais il a fallu moi un peu à comprendre, donc j'espère que cela aidera quelqu'un d'autre.

13
répondu Paul 2011-07-07 20:09:50

worker.Dispose() n'est pas nécessaire, parce que Dispose() est automatiquement appelé. Mais avant de disposer de l'objet, vous devez supprimer tous les gestionnaires d'événements.

Cet article nous en informe.

worker.RunWorkerCompleted -= new RunWorkerCompletedEventHandle(worker_RunWorkerCompleted);
worker.DoWork -= new DoWorkEventHandler(worker_DoWork);
1
répondu AlexN 2012-10-26 10:48:29

Oui, cela semble approprié. Bien sûr, les objets jetables sont mieux gérés avec des blocs using, mais vous n'avez pas cette option ici.

Je crée habituellement mes handers d'arrière-plan avec des durées de vie de formulaire, les réutilise et laisse le code du concepteur gérer l'élimination sur le formulaire. De moins en moins à penser.

0
répondu Michael Petrotta 2010-03-30 01:39:44

Si c'est sur un formulaire" WinForms", laissez le conteneur s'en occuper (voir le code Dispose généré dans le formulaire.Designer.fichier xyz)

En pratique, j'ai trouvé que vous devrez peut-être créer une instance du conteneur et y ajouter le worker (ou un autre companent), si quelqu'un connaît un moyen plus officiel de le faire!!

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

}
0
répondu Paul Kohler 2010-03-30 01:54:40