web-dev-qa-db-fra.com

Comment attendre que BackgroundWorker se termine, puis quitter l'application console

J'ai écrit un exemple d'application console pour tester backgroundworker en utilisant l'un des exemples publiés ici dans Stackoverflow. J'ai un backgroundworker qui commence par la méthode principale mais se termine au milieu de l'opération si j'appuie sur Entrée parce que j'ai écrit un console.readkey dans la méthode principale. Mais je veux qu'il attende que le backgroundworker ait fini de faire le travail, puis quitte l'application. Ceci est mon code.

class Program
{
    private static BackgroundWorker worker = new BackgroundWorker();
    private event EventHandler BackgroundWorkFinished;

    static void Main(string[] args)
    {
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.ProgressChanged += worker_ProgressChanged;
        worker.WorkerReportsProgress = true;
        worker.WorkerSupportsCancellation = true;

        Console.WriteLine("Starting Application...");

        worker.RunWorkerAsync();
        Console.ReadKey();
    }

    static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        Console.WriteLine(e.ProgressPercentage.ToString());
    }

    static void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        Console.WriteLine("Starting to do some work now...");
        int i;
        for (i = 1; i < 10; i++)
        {
            Thread.Sleep(1000);
            worker.ReportProgress(Convert.ToInt32((100.0 * i) / 10));
        }

        e.Result = i;
    }

    static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Console.WriteLine("Value Of i = " + e.Result.ToString());
        Console.WriteLine("Done now...");
    }
}
21
Soham Dasgupta

Voir le Comment attendre l'annulation d'un BackgroundWorker? pour savoir comment communiquer entre votre BackgroundWorker et votre thread principal.

Fondamentalement, vous devez utiliser un événement que vous avez défini à la fin de DoWork pour signaler que DoWork est terminé. Vous avez ensuite WaitOne () sur cet événement dans votre thread principal.

10
Andreas Paulsson

Le but principal d'un Bgw est d'interagir avec Windows MessageQueue. En d'autres termes, il est très utile dans les applications WinForms et WPF.

Une application console n'est pas le bon endroit pour utiliser ou tester un Bgw. Vous obtiendrez des résultats étranges. Imprimez ManagedThreadId aux points clés pour voir ce qui se passe.

Et quelques conseils standard: votre worker_RunWorkerCompleted() devrait vérifier e.ErrorPour l'instant, c'est la même chose que d'avoir un catch{} bloquer.
Toute erreur de DoWork sera désormais levée lorsque vous lirez e.Result, plus complexe à gérer.

4
Henk Holterman

C'est ce que j'ai fait maintenant. Mais la console.readkey() ne fonctionne pas. L'application n'attend pas la fonction ReadKey().

class Program
{
    private static BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();
    private static AutoResetEvent resetEvent = new AutoResetEvent(false);
    static void Main(string[] args)
    {
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.ProgressChanged += worker_ProgressChanged;
        worker.WorkerReportsProgress = true;

        Console.WriteLine("Starting Application...");

        worker.RunWorkerAsync();
        resetEvent.WaitOne();

        Console.ReadKey();
    }

    static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        Console.WriteLine(e.ProgressPercentage.ToString());
    }

    static void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        Console.WriteLine("Starting to do some work now...");
        int i;
        for (i = 1; i < 10; i++)
        {
            Thread.Sleep(1000);
            worker.ReportProgress(Convert.ToInt32((100.0 * i) / 10));
        }

        e.Result = i;

        resetEvent.Set();
    }

    static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Console.WriteLine("Value Of i = " + e.Result.ToString());
        Console.WriteLine("Done now...");
    }

}

Fixing Edit: Déplacé resetEvent.Set() vers l'intérieur DoWork plutôt que dans RunWorkerCompleted. Le gestionnaire d'événements Completed ne sera jamais appelé car le thread principal attend l'événement.

2
Soham Dasgupta