如何使用 WPF 后台工作者
Posted
技术标签:
【中文标题】如何使用 WPF 后台工作者【英文标题】:How to use WPF Background Worker 【发布时间】:2011-07-25 21:49:49 【问题描述】:在我的应用程序中,我需要执行一系列初始化步骤,这些步骤需要 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/… 点击该链接时出现隐私错误。 【参考方案1】:-
使用添加
using System.ComponentModel;
-
声明Background Worker:
private readonly BackgroundWorker worker = new BackgroundWorker();
-
订阅活动:
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
-
实现两种方法:
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
-
根据需要运行工作程序异步。
worker.RunWorkerAsync();
跟踪进度(可选,但通常很有用)
a) 订阅ProgressChanged
事件并在DoWork
中使用ReportProgress(Int32)
b) 设置worker.WorkerReportsProgress = true;
(归功于@zagy)
【讨论】:
有没有办法在这些方法中访问 DataContext?【参考方案2】:您可能还想考虑使用 Task
而不是后台工作人员。
在您的示例中,最简单的方法是Task.Run(InitializationThread);
。
使用任务而不是后台工作人员有几个好处。例如,.net 4.5 中的新 async/await 功能使用Task
进行线程处理。这是一些关于Task
的文档
https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task
【讨论】:
很抱歉发现了这个帖子,但是.net 4.0 和 4.5 添加了一些很酷的东西,比BackgroundWorker
更容易使用。希望引导人们走向它。
现在这个答案已经很老了,请查看async
和await
。这些是以更易读的方式使用任务的语言集成方式。【参考方案3】:
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/
【讨论】:
【参考方案4】:我发现这个 (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;
;
【讨论】:
以上是关于如何使用 WPF 后台工作者的主要内容,如果未能解决你的问题,请参考以下文章