How to use WPF Background Worker
Asked Answered
H

4

193

In my application I need to perform a series of initialization steps, these take 7-8 seconds to complete during which my UI becomes unresponsive. To resolve this I perform the initialization in a separate thread:

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

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

I have read a few articles about the BackgroundWorker and how it should allow me to keep my application responsive without ever having to write a thread to perform lengthy tasks but I haven't had any success trying to implement it, could anyone tell how I would do this using the BackgroundWorker?

Hiragana answered 30/3, 2011 at 8:3 Comment(2)
I found this tutorial useful, it has several concise examples: elegantcode.com/2009/07/03/…Busybody
I get privacy error when clicking on that link.Icarus
S
349
  1. Add using

    using System.ComponentModel;
    
  2. Declare Background Worker:

    private readonly BackgroundWorker worker = new BackgroundWorker();
    
  3. Subscribe to events:

    worker.DoWork += worker_DoWork;
    worker.RunWorkerCompleted += worker_RunWorkerCompleted;
    
  4. Implement two methods:

    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
    }
    
  5. Run worker async whenever your need.

    worker.RunWorkerAsync();
    
  6. Track progress (optional, but often useful)

    a) subscribe to ProgressChanged event and use ReportProgress(Int32) in DoWork

    b) set worker.WorkerReportsProgress = true; (credits to @zagy)

Scarification answered 30/3, 2011 at 8:9 Comment(1)
Is there a way to access the DataContext in those methods?Anabantid
S
44

You may want to also look into using Task instead of background workers.

The easiest way to do this is in your example is Task.Run(InitializationThread);.

There are several benefits to using tasks instead of background workers. For example, the new async/await features in .net 4.5 use Task for threading. Here is some documentation about Task https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task

Schwarz answered 2/6, 2014 at 18:6 Comment(2)
Sorry to unearth this thread, but .net 4.0 and 4.5 added some cool stuff that is way easier to use than BackgroundWorker. Hoping to steer people to it.Schwarz
Now that this answer is super old, check out async and await. These are language integrated ways to use tasks in a much more readable way.Schwarz
W
17
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);  
            }  
        }  
    }  
} 

Also, referr the below link you will understand the concepts of Background:

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

Wittie answered 31/5, 2015 at 5:21 Comment(0)
M
3

I found this (WPF Multithreading: Using the BackgroundWorker and Reporting the Progress to the UI. link) to contain the rest of the details which are missing from @Andrew's answer.

The one thing I found very useful was that the worker thread couldn't access the MainWindow's controls (in it's own method), however when using a delegate inside the main windows event handler it was 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;
};
Mehitable answered 23/9, 2013 at 20:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.