WPF Multithreading with BackgroundWorker

来源:互联网 发布:淘宝的网络广告方式 编辑:程序博客网 时间:2024/04/29 01:14

Most of the platform technologies have always been single-threaded. Which means that you can access the UI controls only from the thread that create it. But in some particular circumstance, we need to run the logic in another thread. This is where the background thread comes into play.

In WPF, we can do that with the Dispatcher using Dispatch.BeginInvoke method. Which executes the specified delegate asynchronously at the specified priority on the thread that the Dispatcher associated with. Unfortunately, this approaches does not allow the target users to report the progress and cancel the process. You need to create a component by yourself to use this Dispacther.BeginInvoke method.

But do not worry, .NET Framework already provides a class called BackgroundWorker to treat this kinds of issues. Which provides the functionalities to report progress and user-cancellation. Besides, it is very convenient for user to use. If you are already familiar with WinForms, you may have encountered this class before.

In the following section, I’d like to illustrate this class background class and show how it does the logic behind the scenes.

Let’s consider such a common scenario. When we launch a application with huge bunches of data to load at the beginning, we need to inform the user that the project is loading instead of doing nothing. This is a very friendly user experience and tell that the application is not blocked now and is still running. Next, let’s just use a simply ProgressBar control to achieve this simply demonstration.

What is included in this topic?

#1 Properties, methods and other elements in BackgroundWorker class.

#2 The steps to use it.

Well, let’s just show it step by step.

#1 Properties, methods and other elements in BackgroundWorker class.

When we type the BackgroundWorker class in Visual Studio IDE and use F12 key to navigate the definition of the class. We can see many members inside of BackgroundWorker. Here I am just going to list some of the most important members.

1) Properties:
WorkerReportsProgress: this property is use to specify whether the BackgroundWorker can report progress updates. True mean that it supports

Progress updates. By contrast, not support. The default value is false.

WorkerSupportsCancellation: this property is used to indicated whether the BackgroundWorker supports asynchronous cancellation.

2) Methods:

RunWorkerAsync method is to start the execution of the background operation.

CancelAsync: request cancellation of a pending background operation.

3) Events: DoWork ProgressChanged RunWorkerCompleted.

These three events mean as their names implies..

Ok, the following is the full sample code of the sample.

XAML:

<StackPanel >
    <
Button Margin="8,25,0,0"
          
 x:Name="btnStart" 
          
 Content="Start"
          
 Width="80"
          
 Height="27"
          
 Click="StartWorker"/>
    <
ButtonIsEnabled="False"
           
 x:Name="btnCancel"
           
 Width="80" 
          
 Height="27"
          
 Content="Cancel"
          
 Click="CancelWorker"/>
    <
ProgressBar Margin="8,0,8,107"
               
 x:Name="_progressBar"
               
 VerticalAlignment="Bottom"
               
 Height="23"Maximum="10"/>
</
StackPanel>

In the code behind:

public partial class Window1 : System.Windows.Window
 
 {
      private BackgroundWorker _worker;
      public Window1()
      {
          InitializeComponent();
      }
      private void StartWorker(object sender, RoutedEventArgs e)
      {
          _worker = new BackgroundWorker();
          //Gets or sets a value indicating whether the BackgroundWorker can report progress updates.
         
 _worker.WorkerReportsProgress = true;
          //Gets or sets a value indicating whether the BackgroundWorker supports asynchronous cancellation.
         
 _worker.WorkerSupportsCancellation = true;
          //Starts execution of a background operation.
         
 _worker.RunWorkerAsync();
          btnStart.IsEnabled = false;
          btnCancel.IsEnabled = true;
          _worker.DoWork += delegate(object s, DoWorkEventArgs args)
          {
              BackgroundWorker worker = s as BackgroundWorker;
              for (int i = 0; i < 10; i++)
              {
                  if (worker.CancellationPending)
                  {
                      args.Cancel = true;
                      return;
                  }
                  Thread.Sleep(100);
                  //Raises the System.ComponentModel.BackgroundWorker.ProgressChanged event.
                 
 worker.ReportProgress(i+1 );
              }
          };
          _worker.ProgressChanged += delegate(object s, ProgressChangedEventArgsargs)
          {
              _progressBar.Value = args.ProgressPercentage;
          };
          _worker.RunWorkerCompleted += delegate(object s,RunWorkerCompletedEventArgs args)
          {
              btnStart.IsEnabled = true;
              btnCancel.IsEnabled = false;
              _progressBar.Value = 0;
          };
      }
      private void CancelWorker(object sender, RoutedEventArgs e)
      {
          _worker.CancelAsync();
      }
  }

原创粉丝点击