web-dev-qa-db-fra.com

Comment utiliser WPF Background Worker

Je suis un débutant avec WPF, dans mon application, je dois effectuer une série d'étapes d'initialisation. Celles-ci prennent 7 à 8 secondes, au cours desquelles mon interface utilisateur cesse de répondre. Pour résoudre cela, j'effectue l'initialisation dans un thread séparé:

    public void Initialization()
    {
        Thread initThread = new Thread(new ThreadStart(InitializationThread));
        initThread.Start();
    }

    public void InitializationThread()
    {
        outputMessage("Initializing...");
        //DO INITIALIZATION
        outputMessage("Initialization Complete");
    }

J'ai lu quelques articles sur BackgroundWorker et comment cela devrait me permettre de garder mon application réactive sans avoir à écrire un fil de discussion pour effectuer de longues tâches, mais je n'ai jamais réussi à l'implémenter. dire comment je ferais cela en utilisant le BackgroundWorker?

Merci Eamonn

174
Eamonn McEvoy
  1. Ajouter en utilisant
using System.ComponentModel;
  1. Déclarer Travailleur de fond :
private readonly BackgroundWorker worker = new BackgroundWorker();
  1. S'abonner à des événements:
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
  1. Implémenter deux méthodes:
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
  // run all background tasks here
}

private void worker_RunWorkerCompleted(object sender, 
                                           RunWorkerCompletedEventArgs e)
{
  //update ui once worker complete his work
}
  1. Exécutez worker async chaque fois que vous en avez besoin.
worker.RunWorkerAsync();
  1. Suivre les progrès (facultatif, mais souvent utile)

    a) vous abonner à l'événement ProgressChanged et utiliser ReportProgress(Int32) dans DoWork

    b) mettre worker.WorkerReportsProgress = true; (crédits à @zagy)

312
Andrew Orsich

Vous voudrez peut-être aussi envisager d'utiliser Task à la place de travailleurs d'arrière-plan.

La méthode la plus simple consiste à utiliser Task.Run(InitializationThread); dans votre exemple.

L'utilisation de tâches au lieu de travailleurs d'arrière-plan présente plusieurs avantages. Par exemple, les nouvelles fonctionnalités async/wait de .net 4.5 utilisent Task pour les threads. Voici de la documentation sur Taskhttp://msdn.Microsoft.com/en-us/library/system.threading.tasks.task (v = vs.110) .aspx

36
Owen Johnson
using System;  
using System.ComponentModel;   
using System.Threading;    
namespace BackGroundWorkerExample  
{   
    class Program  
    {  
        private static BackgroundWorker backgroundWorker;  

        static void Main(string[] args)  
        {  
            backgroundWorker = new BackgroundWorker  
            {  
                WorkerReportsProgress = true,  
                WorkerSupportsCancellation = true  
            };  

            backgroundWorker.DoWork += backgroundWorker_DoWork;  
            //For the display of operation progress to UI.    
            backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged;  
            //After the completation of operation.    
            backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;  
            backgroundWorker.RunWorkerAsync("Press Enter in the next 5 seconds to Cancel operation:");  

            Console.ReadLine();  

            if (backgroundWorker.IsBusy)  
            { 
                backgroundWorker.CancelAsync();  
                Console.ReadLine();  
            }  
        }  

        static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)  
        {  
            for (int i = 0; i < 200; i++)  
            {  
                if (backgroundWorker.CancellationPending)  
                {  
                    e.Cancel = true;  
                    return;  
                }  

                backgroundWorker.ReportProgress(i);  
                Thread.Sleep(1000);  
                e.Result = 1000;  
            }  
        }  

        static void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)  
        {  
            Console.WriteLine("Completed" + e.ProgressPercentage + "%");  
        }  

        static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)  
        {  

            if (e.Cancelled)  
            {  
                Console.WriteLine("Operation Cancelled");  
            }  
            else if (e.Error != null)  
            {  
                Console.WriteLine("Error in Process :" + e.Error);  
            }  
            else  
            {  
                Console.WriteLine("Operation Completed :" + e.Result);  
            }  
        }  
    }  
} 

De plus, en vous référant au lien ci-dessous, vous comprendrez les concepts de Background:

http://www.c-sharpcorner.com/UploadFile/1c8574/threads-in-wpf/

13
Gul Md Ershad

en plus de ce qu'a dit Andrew Orsich, vous voudrez peut-être lire quelques exemples à ce sujet.

voici un exemple de code utilisant background worker et une barre de progression

http://devtoolshed.com/content/c-download-file-progress-bar

et voici un petit tutoriel

http://www.dotnetperls.com/backgroundworker

et il y a un lien pour un autre exemple de progressbar + backgroundworker à la fin du tutoriel.

5
bliss

J'ai trouvé ceci ( WPF Multithreading: Utiliser BackgroundWorker et signaler le progrès à l'interface utilisateur. Link ) pour contenir le reste des détails manquants dans la réponse de @ Andrew.

La seule chose que j'ai trouvée très utile est que le thread de travail ne pouvait pas accéder aux contrôles de MainWindow (selon sa propre méthode). Cependant, l'utilisation d'un délégué dans le gestionnaire d'événements principal de Windows était possible.

worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
    pd.Close();
    // Get a result from the asynchronous worker
    T t = (t)args.Result
    this.ExampleControl.Text = t.BlaBla;
};
3
lko

Essayez ce lien classe BackgroundWorker dans MSDN qui contient un exemple d'utilisation.

1
Anuraj