c# backgroundWorker 没有引发 ProgressChanged 或 RunWorkerCompleted 事件
Posted
技术标签:
【中文标题】c# backgroundWorker 没有引发 ProgressChanged 或 RunWorkerCompleted 事件【英文标题】:c# backgroundWorker not raising ProgressChanged or RunWorkerCompleted events 【发布时间】:2011-08-31 19:08:01 【问题描述】:使用 C# .NET 3.5。
看来我不是唯一一个,因为搜索似乎提出了很多类似的问题,但是阅读它们我似乎仍然缺少解决方案。
我正在通过单击我的 UI 上的按钮引发一个事件,然后应该启动一个 backgroundWorker 以完成一些耗时的工作 - 在这种情况下,我希望它从表单中收集信息并 a) 编写到 xml 文件以及 b) 将信息插入远程数据库。
我相信这正是 backgroundWorker 的设计和意图。
这是事件引发代码。
private void btnFinish_Click(object sender, EventArgs e)
clkFinish.setInstant();
curAct.setTimeFinish(DateTime.Now);
btnStart.Enabled = true;
bgwDataWorker.RunWorkerAsync();
for (int i = 0; i < 20; i++)
Console.WriteLine("Thread a: " + i);
Thread.Sleep(100);
if (i == (20 - 1))
Console.WriteLine("Finished");
如您所见,我有一些代码用于平衡后台工作人员代码,这里是:
private void bgwDataWorker_DoWork(object sender, DoWorkEventArgs e)
Console.WriteLine("Running in a different thread now");
int count = 0;
for (int i = 0; i < 21; i++)
Console.WriteLine("Thread b: " + i);
Thread.Sleep(100);
(sender as BackgroundWorker).ReportProgress(5 * i, null);
if (i == (21 - 1))
count = i;
e.Result = count;
到目前为止,一切似乎都在进行中。
我的问题是当 DoWork 方法中的代码完成时,什么都没有发生。下面是 ProgressChanged 和 RunWorkerComplete 方法。
private void bgwDataWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
Console.WriteLine(e.ProgressPercentage);
private void bgwDataWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
Console.WriteLine("Result is " + e.Result.ToString());
这让我很困惑。
我尝试运行examples from MSDN,但遇到了同样的问题。由于某种原因根本没有引发 RunWorkerCompleted 和 ReportProgress 事件,我不明白为什么。
感谢阅读。
艾伦
【问题讨论】:
您在控制台应用程序中使用后台工作程序,对吗?您是否看到任何控制台输出?这看起来更像 Windows 应用程序,因为您在顶部有一个按钮单击事件处理程序。运行应用时是否有控制台窗口? 乔德雷尔,谢谢。不,这不是控制台应用程序,它是基于 Windows 窗体的应用程序。我使用的是 Visual Studio 10,console.writeline 输出来自调试输出。 @inksmithy:我看到了同样的行为——你解决了吗? @BlueChippy 不幸的是,不,我最终把所有东西都扔进了计时器。这不是一个理想的解决方案,但由于计时器使用自己的线程来运行它的任务,所以它完成了工作。我仍在努力寻找解决方案。 【参考方案1】:我最近遇到了这个问题。这是因为我让主线程休眠直到后台线程完成,这阻止了更新的执行。
我通过将我的对象(包含工作线程)包装到另一个线程中来解决这个问题,以便可以执行进度更新,更改主线程中的值允许我的睡眠线程继续。
【讨论】:
【参考方案2】:我有一个项目 [A],(不久前建立)进度条正常工作。当前应用 [B] 未报告进度。出于某种原因,应用程序 [A] 连接了进度和工作完成事件处理程序。所以,我在应用程序 [B] 中连接了事件处理程序,它正在工作。处理程序被复制到 Designer.cs 部分类文件中。 (假设他们可以进入 form.cs 部分类)。
//
// backgroundWorker1
//
this.backgroundWorker1.WorkerReportsProgress = true;
this.backgroundWorker1.WorkerSupportsCancellation = true;
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
this.backgroundWorker1.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged);
this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
//
希望这会有所帮助。不知道为什么应用程序 [A] 是通过使用工具箱将后台工作人员拖放到表单设计窗口来连接的。使用 VS2012 和 Windows 7。
另外,我正在计算进度百分比,由于某种原因,列表框中的项目数乘以选定复选框的数量超过 100% - 它抛出并出错。因此,我将百分比限制为 99,并将这部分作为我的逻辑,以便将进度百分比报告回事件。
【讨论】:
【参考方案3】:Inksmithy,您提到您已重命名 BackgroundWorker。请注意,当您执行此操作时,表单设计器不会自动更改对旧 DoWork 和 RunWorkerCompleted 方法的引用。因此,在表单设计器中,单击 BackgroundWorker,然后单击属性窗口中的事件图标(闪电),并仔细检查它是否指向正确的事件方法名称。
【讨论】:
感谢您的回答,我已经检查过了,但我没有在最初的问题中提及它。这是一个很好的观点,但很容易错过。 我遇到了和 op 一样的问题。即使我没有更改后台工作人员的名称,后台工作人员属性也没有设置事件方法名称。通过执行 Heliac 的建议,解决了我的问题。【参考方案4】:我遇到了同样的问题,我只是想出了答案。
在 backgroundworker 的属性中,确保 ProgressChanged 和 RunWorkerCompleted 列出其函数的名称(我的分别称为“backgroundWorker1_ProgressChanged”和“backgroundWorker1_RunWorkerCompleted”)。
【讨论】:
【参考方案5】:你遗漏了一个重要的部分 - 一个允许它引发事件的布尔标志
bgwDataWorker.WorkerReportsProgress = true;
bgwDataWorker.WorkerSupportsCancellation = true;
【讨论】:
感谢您的回复,是的,这两个标志都已设置。【参考方案6】:将 WorkerReportsProgress
属性设置为 True。
【讨论】:
感谢您的回复,该标志已在变量上设置。【参考方案7】:您没有错过设置这些变量,是吗?
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
这也可能是 DoWork 方法中的一个异常,未处理。
【讨论】:
桑兹,感谢您的回复。我在 Visual Studio 2010 中使用了可视化编辑器并将 backgroundWorker 拖到表单上,然后在属性窗格中将这两个属性都调整为“true”。我已经重命名了 backgroundWorker,这会产生影响吗?另外,我在调试输出中没有看到任何异常,我只是看到工作停止。 我会用一个明确的 DoWork-Method 来尝试它,也许只是一个 Console.WriteLine 调用,然后看看它是否有效。 我已将 DoWork 方法编辑为: private void bgwDataWorker_DoWork(object sender, DoWorkEventArgs e) Thread.Sleep(1000); Console.WriteLine("再次休息,1 秒");线程.睡眠(1000); String fin = "现在完成"; e.Result = fin;我已将 RunWorkerCompleted 方法更改为: private void bgwDataWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) Console.WriteLine("Result is " + (String)e.Result); Minimarkdown 失败了,对不起。结果是,行为没有改变。我不明白这一点,我的环境是 Windows 7 Ultimate,我在一个新的四核处理器上运行。有足够的内存。以上是关于c# backgroundWorker 没有引发 ProgressChanged 或 RunWorkerCompleted 事件的主要内容,如果未能解决你的问题,请参考以下文章