Verwendung von WPF Background Worker

177

In meiner Anwendung muss ich eine Reihe von Initialisierungsschritten ausführen. Diese dauern 7 bis 8 Sekunden, während derer meine Benutzeroberfläche nicht mehr reagiert. Um dies zu beheben, führe ich die Initialisierung in einem separaten Thread durch:

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

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

Ich habe ein paar Artikel darüber gelesen BackgroundWorkerund wie es mir ermöglichen sollte, meine Anwendung reaktionsfähig zu halten, ohne jemals einen Thread schreiben zu müssen, um langwierige Aufgaben auszuführen, aber ich hatte keinen Erfolg bei der Implementierung, könnte jemand sagen, wie ich es machen würde dies mit dem BackgroundWorker?

Eamonn McEvoy
quelle
Ich fand dieses Tutorial nützlich, es enthält einige kurze Beispiele: elegantcode.com/2009/07/03/…
GrandMasterFlush
Beim Klicken auf diesen Link wird ein Datenschutzfehler angezeigt.
LittleBirdy

Antworten:

319
  1. Hinzufügen mit
using System.ComponentModel;
  1. Hintergrundarbeiter deklarieren :
private readonly BackgroundWorker worker = new BackgroundWorker();
  1. Abonnieren Sie Veranstaltungen:
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
  1. Implementieren Sie zwei Methoden:
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. Führen Sie Worker async aus, wann immer Sie dies benötigen.
worker.RunWorkerAsync();
  1. Fortschritt verfolgen (optional, aber oft nützlich)

    a) abonnieren Sie das ProgressChangedEreignis und verwenden Sie es ReportProgress(Int32)inDoWork

    b) setzen worker.WorkerReportsProgress = true;(Credits auf @zagy)

Andrew Orsich
quelle
Gibt es in diesen Methoden eine Möglichkeit, auf den DataContext zuzugreifen?
susieloo_
36

Vielleicht möchten Sie auch die Verwendung untersuchen Task von Hintergrundarbeitern anstelle von Hintergrundarbeitern untersuchen.

Der einfachste Weg, dies zu tun, ist in Ihrem Beispiel Task.Run(InitializationThread); .

Die Verwendung von Aufgaben anstelle von Hintergrundarbeitern bietet mehrere Vorteile. Beispielsweise werden die neuen asynchronen / wartenden Funktionen in .net 4.5 Taskzum Threading verwendet. Hier finden Sie eine Dokumentation zu Task https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task

Owen Johnson
quelle
11
Es tut uns leid, diesen Thread zu entdecken, aber .net 4.0 und 4.5 haben einige coole Sachen hinzugefügt, die viel einfacher zu bedienen sind als BackgroundWorker. In der Hoffnung, die Leute dorthin zu lenken.
Owen Johnson
1
Jetzt, da diese Antwort super alt ist, check out asyncund await. Dies sind sprachintegrierte Methoden, um Aufgaben besser lesbar zu nutzen.
Owen Johnson
14
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);  
            }  
        }  
    }  
} 

Verweisen Sie auch auf den folgenden Link, um die Konzepte von zu verstehen Background:

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

Gul Md Ershad
quelle
3

Ich habe das gefunden ( WPF-Multithreading: Verwenden des BackgroundWorker und Melden des Fortschritts an die Benutzeroberfläche. Link ) den Rest der Details enthält, die in @ Andrews Antwort fehlen.

Das einzige, was ich sehr nützlich fand, war, dass der Arbeitsthread nicht auf die Steuerelemente des MainWindow zugreifen konnte (in seiner eigenen Methode), aber wenn ein Delegat im Haupt-Windows-Ereignishandler verwendet wurde, war dies möglich.

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;
};
lko
quelle