web-dev-qa-db-fra.com

Manière appropriée d'éliminer un BackGroundWorker

Serait-ce une bonne façon de se débarrasser d'un BackGroundWorker? Je ne sais pas s'il est nécessaire de supprimer les événements avant d'appeler .Dispose (). Appelle également .Dispose () à l'intérieur du 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
galford13x

BackgroundWorker dérive de Component. Component implémente l'interface IDisposable. À son tour, BackgroundWorker hérite de la méthode Dispose ().

Dériver à partir de Component est un avantage 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 s’occupe de cela automatiquement. Recherchez dans le fichier Designer.cs un Form pour le champ "composants". Sa méthode Dispose () générée automatiquement appelle la méthode Dispose () pour tous les composants.

Cependant, BackgroundWorker n’a aucun membre à élimination obligatoire. Il ne remplace pas Dispose (). Son implémentation de base, Component.Dispose (), s'assure uniquement que le composant est supprimé de la collection "components". Et soulevez l'événement Disposed. Mais ne dispose pas autrement quoi que ce soit.

Bref récit: si vous déposez une BGW sur un formulaire, tout est réglé automatiquement, vous n'avez pas à vous aider. Si vous ne le déposez pas sur un formulaire, il ne s'agit pas d'un élément d'une collection de composants et rien ne doit être fait.

Vous n'êtes pas obligé d'appeler Dispose () .

68
Hans Passant

En retard au jeu, mais je viens de rencontrer un scénario lié à votre question que je pensais partager. Si vous créez votre agent 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 une fois l'opération terminée, ils seront incrémentés et exécutés 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 logiciel DoWork se déclenche une fois, une fois, deux fois, etc. C'est probablement une évidence pour la plupart des gens, mais il m'a fallu un peu de temps pour le comprendre. J'espère donc que cela aidera quelqu'un d'autre.

13
Paul

worker.Dispose() n'est pas requis, car 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
AlexN

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 généralement mes documents d'arrière-plan avec les durées de vie des formulaires, les réutilise et laisse le code du concepteur gérer l'élimination des formulaires fermés. Moins de réflexion.

0
Michael Petrotta

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

Dans la pratique, j'ai découvert qu'il vous fallait peut-être créer une instance du conteneur et y ajouter le travailleur (ou un autre compagnon), si quelqu'un connaissait un moyen plus officiel de le faire, criez !!

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
Paul Kohler