如何使用WPF背景工


177

在我的应用程序中,我需要执行一系列初始化步骤,这些步骤需要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


我发现这个教程是有用的,它有几个简洁的例子:elegantcode.com/2009/07/03/...
GrandMasterFlush

单击该链接时出现隐私错误。
LittleBirdy

Answers:


319
  1. 使用添加
using System.ComponentModel;
  1. 声明背景工作者
private readonly BackgroundWorker worker = new BackgroundWorker();
  1. 订阅事件:
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
  1. 实现两种方法:
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。
worker.RunWorkerAsync();
  1. 跟踪进度(可选,但通常很有用)

    一)订阅ProgressChanged事件和使用ReportProgress(Int32)DoWork

    b)设置worker.WorkerReportsProgress = true;(贷方为@zagy)


在这些方法中是否可以访问DataContext?
susieloo_

36

您可能还想研究使用Task而不是后台工作人员。

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

使用任务而不是后台工作者有很多好处。例如,.net 4.5中新的异步/等待功能Task用于线程。这是有关https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.tasks.task的一些文档Task


11
很抱歉,发现此线程,但是.net 4.0和4.5添加了一些很酷的东西,这些东西比起来更容易使用BackgroundWorker。希望引导人们去做。
Owen Johnson

1
现在,这个答案已经过时了,请查看asyncawait。这些是语言集成的方式,以一种更具可读性的方式使用任务。
欧文·约翰逊

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

另外,请参考下面的链接,您将了解以下概念Background

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


3

我发现了这一点(WPF多线程:使用BackgroundWorker并将进度报告到UI。)包含@Andrew的答案中缺少的其余详细信息。

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

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;
};
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.