未调用 BackgroundWorker DoWork 函数
Posted
技术标签:
【中文标题】未调用 BackgroundWorker DoWork 函数【英文标题】:BackgroundWorker DoWork function is not being called 【发布时间】: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 和 ProgressTask.Run
将在另一个线程上执行。
为什么要检查backgroundWorker == null
?当然是null
,你在表单的构造函数中。除非那里发生了您没有显示的其他事情,例如尝试以某种方式回收此表单。将backgroundWorker.RunWorkerAsync();
移动到Form.Load
或Form.OnLoad
(或OnShown()
以查看表单是否显示已呈现)。如果它没有启动,那么你不会让它启动,因为其他东西阻塞了 UI 线程,所以这行代码永远不会执行。
【参考方案1】:
以下是使用 Progress<int>
和 Task.Run
的方法:
public frmLoading()
InitializeComponent();
IProgress<int> progress = new Progress<int>(p =>
//update value of progress bar
progressBar1.Value = p;
//set the text of the progress bar
this.Text = p.ToString();
);
Task.Run(async () =>
for (int i = 1; i <= 100; i++)
await Task.Delay(TimeSpan.FromSeconds(0.1));
progress.Report(i);
);
我个人更喜欢微软的响应式框架:
public frmLoading()
InitializeComponent();
Observable
.Interval(TimeSpan.FromSeconds(0.1))
.Take(100)
.ObserveOn(this)
.Select(p => p + 1)
.Subscribe(p =>
//update value of progress bar
progressBar1.Value = p;
//set the text of the progress bar
this.Text = p.ToString();
);
【讨论】:
以上是关于未调用 BackgroundWorker DoWork 函数的主要内容,如果未能解决你的问题,请参考以下文章