【发布时间】:2021-01-03 00:57:27
【问题描述】:
我在我的 C# WinForms 应用程序中创建了一个加载表单,该表单在长流程中显示。 我在我的加载表单中添加了一个进度条,我想更新它以向用户提供一些加载反馈。
在我的加载表单代码中,我创建了一个新的 BackgroundWorker 并添加了 DoWork 和 ProgressChanged 事件处理程序。 问题是没有调用 backgroundWorker_ProgressChanged。我在函数中插入了断点,它们没有被捕获。
我哪里错了?任何帮助表示赞赏。谢谢。
frmLoading:
public frmLoading()
{
InitializeComponent();
//check if bg worker is null
if (backgroundWorker == null)
{
backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += backgroundWorker_DoWork;
backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged;
}
backgroundWorker.WorkerReportsProgress = true;
//start
backgroundWorker.RunWorkerAsync();
}
backgroundWorker_DoWork:
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i <= 100; i++)
{
Thread.Sleep(100);
backgroundWorker.ReportProgress(i);
}
}
backgroundWorker_ProgressChanged:
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//update value of progress bar
progressBar1.Value = e.ProgressPercentage;
//set the text of the progress bar
this.Text = e.ProgressPercentage.ToString();
}
【问题讨论】:
-
使用调试器,Debug > Windows > Threads,观察主线程在做什么。它必须处于空闲状态,在 Application.Run() 中执行才能执行此事件处理程序。永远不要让它执行昂贵的代码,这是工作线程的工作。
-
BGW 自 2012 年以来已过时,完全被 Task.Run 和 Progress
取代。不过,要定期更新 UI,您只需要a Timer,而不是后台线程。创建一个简单的 Winforms 计时器,在加载时启用它并在完成后禁用它,或者当 ProgressBar 达到最大值时禁用它 -
谢谢,我会看看 Task.Run。我认为这项工作需要在一个单独的线程上进行,因为我已经在另一个表单的后台运行了大型进程。
-
@PaulAlexander -
Task.Run将在另一个线程上执行。 -
为什么要检查
backgroundWorker == null?当然是null,你在表单的构造函数中。除非那里发生了您没有显示的其他事情,例如尝试以某种方式回收此表单。将backgroundWorker.RunWorkerAsync();移动到Form.Load或Form.OnLoad(或OnShown()以查看表单是否显示已呈现)。如果它没有启动,那么你不会让它启动,因为其他东西阻塞了 UI 线程,所以这行代码永远不会执行。
标签: c# multithreading winforms backgroundworker background-thread