首页 文章

如何使用WPF后台工作程序

提问于
浏览
170

我是 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 执行此操作?

谢谢,Eamonn

6 回答

  • 34

    1.添加以下内容: using System.ComponentModel;

    2.Declare background worker

    private readonly BackgroundWorker worker = new BackgroundWorker();
    

    3.订阅活动:

    worker.DoWork += worker_DoWork;
    worker.RunWorkerCompleted += worker_RunWorkerCompleted;
    

    4.实现两种方法:

    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.无论何时需要,运行工作异步 .

    worker.RunWorkerAsync();
    

    此外,如果要报告进程进度,则应订阅 ProgressChanged 事件,并使用 DoWork 方法中的 ReportProgress(Int32) 来引发事件 . 还设置如下: worker.WorkerReportsProgress = true; (感谢@zagy)

    希望这有帮助 .

  • 12

    您可能还想查看使用 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的文档

  • 1
    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/

  • 304

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

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

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

    这是一个小教程

    http://www.dotnetperls.com/backgroundworker

    并且在本教程结尾处有另一个progressbar backgroundworker示例的链接 .

  • 5

    我发现这个(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;
    };
    
  • 3

    试试这个链接BackgroundWorker Class in MSDN,其中包含如何使用它的示例 .

相关问题