如何使用WPF后台工作程序

时间:2011-03-30 08:03:17

标签: c# wpf multithreading backgroundworker

我是 WPF 的初学者,在我的应用程序中,我需要执行一系列初始化步骤,这些步骤需要7-8秒才能完成,在此期间我的UI变得无法响应。为了解决这个问题,我在一个单独的线程中执行初始化:

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

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

我已经阅读了一些关于BackgroundWorker的文章以及它应该如何让我保持我的应用程序响应,而不必编写一个线程来执行冗长的任务但我没有成功尝试实现它,有谁可以告诉我如何使用BackgroundWorker

来做到这一点

谢谢, 埃蒙

6 个答案:

答案 0 :(得分:308)

  1. 使用
  2. 添加
    using System.ComponentModel;
    
    1. 声明Background Worker
    2. private readonly BackgroundWorker worker = new BackgroundWorker();
      
      1. 订阅活动:
      2. worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        
        1. 实施两种方法:
        2. 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. 在需要时运行worker async。
          2. worker.RunWorkerAsync();
            
            1. 跟踪进度(可选,但通常很有用)

              a)订阅ProgressChanged个活动并使用ReportProgress(Int32)中的DoWork

              b)设置worker.WorkerReportsProgress = true;(信用到@zagy)

答案 1 :(得分:35)

您可能还希望使用Task而不是后台工作人员。

最简单的方法是在您的示例中Task.Run(InitializationThread);

使用任务而不是后台工作程序有几个好处。例如,.net 4.5中的新async / await功能使用Task进行线程处理。以下是有关Task的一些文档 http://msdn.microsoft.com/en-us/library/system.threading.tasks.task(v=vs.110).aspx

答案 2 :(得分:12)

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);  
            }  
        }  
    }  
} 

另外,请参阅以下链接,您将了解Background

的概念

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

答案 3 :(得分:5)

除了Andrew Orsich所说的,也许你想阅读一些关于它的例子。

这是使用后台工作程序和进度条的示例代码

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

这是一个小教程

http://www.dotnetperls.com/backgroundworker

并且在教程结尾处有另一个进度条+后台工作示例的链接。

答案 4 :(得分:3)

我发现这个(WPF Multithreading: Using the BackgroundWorker and Reporting the Progress to the UI. link)包含了@ Andrew答案中遗漏的其他细节。

我发现非常有用的一件事是工作线程无法访问MainWindow的控件(在它自己的方法中),但是当在主窗口事件处理程序中使用委托时,它是可能的。

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

答案 5 :(得分:1)

请尝试此链接BackgroundWorker Class in MSDN,其中包含如何使用它的示例。