使用BackgroundWorker类时在线程之间传递数据的最佳方式

问题描述 投票:0回答:1

我正在开发一个 Winforms 应用程序。用户将通过按下按钮来启动一项耗时的任务。我不希望我的 UI 冻结,而且我还希望信息不断从该任务返回,然后可用于更新 UI 控件和进度栏。

我进行了研究,看起来 BackgroundWorker 类适用于这些类型的用例。但是,我查看了很多示例,但不清楚如何将数据从工作线程传递回 UI 线程。大多数示例只是专注于通过 ReportProgress() 方法传回百分比完整数字,而 ProgressChanged 事件处理程序是我们被告知与 UI 交互的地方。

这是我到目前为止所做的:

    通过名为“backgroundWorker1”的组件工具箱创建了一个后台工作参考
  1. 为 UI 按钮控件创建按钮单击事件处理程序
  2. 在事件处理程序内部,我调用 backgroundWorker1.RunWorkerAsync();
  3. 在backgroundWorker1_DoWork()方法中实现了我的耗时任务。
文献指出不要尝试在 DoWork() 方法内与 UI 进行交互,而是通过 ProgressChanged 事件处理程序进行交互。但是如何将数据传递给该事件处理程序以便它可以更新 UI 控件?

任何见解都值得赞赏。

c# .net winforms
1个回答
0
投票
您可以发送一些复杂的用户状态以及进度:

private Dictionary<int, string> _backgroundSteps = new Dictionary<int, string>() { [1] = "Preparing frobbles for {0}", [2] = "Executing wibbles for {0}", [3] = "Cleaning up {0} frobbles and {1} wibbles" }; private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { //prepare frobbles var database = new DB(); var preparingFor = database.GetUser(); backgroundWorker1.ReportProgress(1, new string[] { preparingFor }); PrepareFrobbles(); backgroundWorker1.ReportProgress(2, new string[] { preparingFor }); ExecuteWibbles(); backgroundWorker1.ReportProgress(3, new string[] { database.CountFrobbles().ToString(), database.CountWibbles().ToString() }); CleanUp(); } private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { _statusLabel.Text = string.Format(_backgroundSteps[e.ProgressPercentage], (string[])e.UserState); }
在这里,我使用进度来计算 3 个步骤的过程,随消息一起传递一些变化的状态,并简单地用消息更新标签。我可以更多地参与 ProgressChanged,使用条件逻辑来根据传递的 int 做不同的事情,更好地利用状态对象等..

或者我什至无法使用状态重载,只需报告 int,然后通过一些标签面板循环突出显示该过程处于哪个阶段等。关于如何使用它,这是相当开放的


这些天我们可能会使用任务异步模式,并且我们的方法看起来像这样:

private async Task DoSomeLongWork(){ statusLabel.Text = "Preparing frobbles"; await PrepareFrobblesAsync(); statusLabel.Text = "Executing wibbles"; await ExecuteWibblesAsync(); statusLabel.Text = "Executing wibbles"; await CleanUpAsync(); }
执行此操作的代码是 UI 线程,因此它设置文本是安全的。 UI 线程不会陷入准备 frobble 和执行 wibbles 的漫长工作中;当控制它的任务正在等待时,UI 线程会消失回到它原来的位置,继续正常的绘制 UI 工作。当 frobbles 准备好(例如)并且任务完成时,线程从 

await PrepareFrobblesAsync

 之后恢复执行此代码,设置另一个状态,然后在等待执行 wibbles 等时再次消失。
    

© www.soinside.com 2019 - 2024. All rights reserved.