如何使用 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

199460 次浏览
  1. 添加使用

    using System.ComponentModel;
    
  2. 声明 背景工作者:

    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 异步。

    worker.RunWorkerAsync();
    
  6. 跟踪进度(可选,但通常很有用)

    A)订阅 ProgressChanged事件并在 DoWork中使用 ReportProgress(Int32)

    B)设置 worker.WorkerReportsProgress = true;(学分到@zagy)

我发现这个(WPF 多线程: 使用 BackoundWorker 并将进度报告到 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;
};

您可能还需要考虑使用 Task代替后台工作人员。

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

使用任务而不是后台工作者有几个好处。中的新异步/等待特性。Net 4.5使用 Task进行线程处理。下面是一些关于 Task的文档 Https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task

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/