我试图运行一个下面的代码来测试BackgroundWorker,但是它给我带来了很多问题:
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace BackgroundWorkingTest
{
public partial class Form1 : Form
{
BackgroundWorker backgroundWorker1 = new BackgroundWorker();
int counter;
public Form1()
{
InitializeComponent();
backgroundWorker1 = new BackgroundWorker
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
backgroundWorker1.DoWork += BackgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged += BackgroundWorker1_ProgressChanged;
backgroundWorker1.RunWorkerCompleted += BackgroundWorker1_RunWorkerCompleted;
}
private void StartButton_Click(object sender, EventArgs e) // Start
{
counter = 0;
backgroundWorker1.RunWorkerAsync();
}
private void CancelButton_Click(object sender, EventArgs e) // Cancel
{
backgroundWorker1.CancelAsync();
progressLabel.Text = "0";
}
private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e) // DoWork
{
int i;
for (i = 0; i < 123456; i++)
{
// Application.DoEvents(); // This line doesn't help
// Thread.Sleep(1); // Enable this line solve the problem
backgroundWorker1.ReportProgress(i + 1);
counter++;
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
return;
}
}
}
private void BackgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) // Progress
{
progressLabel.Text = counter.ToString();
progressLabel.Refresh();
}
private void BackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) // Completed
{
if (e.Cancelled)
MessageBox.Show("Operation Cancelled");
else
MessageBox.Show("Operation Completed");
}
}
}
**1.**例如,在BackgroundWorker1_DoWork()方法中,您可以看到以下命令:
Thread.Sleep(1);
如果我禁用它,则“取消”按钮没有响应。我单击它几次,但它没有停止进程,也没有收到“操作已取消”消息。
如果我启用它,它就会工作,但我不希望在我的线程中有任何Sleep(1)命令,因为它只会减慢进程,我不希望这样。
如果启用命令:
Application.DoEvents();
它一点帮助都没有,而且“取消”按钮在计数过程中也没有响应。
**2.**我看到的另一个问题是,如果我使用以下命令:
progressLabel.Refresh();
在ProgressChanged()事件中,会发生一些非常奇怪的事情。我可以在面板上看到它完成了计数,标签上显示:“123456”。但它花了几乎一分钟后,直到它显示我的“操作完成”的消息。
如果在标签显示“123456”之后,我在ProgressChanged()方法中设置了一个断点,那么我会看到它不断进入该方法,并且e.ProgressPercentage参数一直在上升。
怎么会呢?如果我在面板上看到“123456”,它不是说流程已经完成了吗?如果已经完成了,为什么它没有马上显示“操作完成”的信息呢?
**3.**如果我删除了“progressLabel.Refresh()”行,那么在标签显示“123456”之后,我会立即收到“Operation Completed”消息,但是它不会显示0到123456之间的计数(当启用Refresh()命令时,我会看到这一点)。
**4.**另一件我不太明白的事是:
当我将代码更改为使用多个BackgroundWorkers的数组而不是仅使用一个BackgroundWorkers时:
BackgroundWorker[] backgroundWorker1 = new ....
在启用Sleep(1)的情况下,我没有收到任何错误消息,尽管所有线程都将文本设置为相同的标签,并将值写入相同的计数器。
这有意义吗?为什么我没有得到任何运行时错误,从几个BackgroundWorker线程在同一时间更新相同的标签?
非常感谢。
1条答案
按热度按时间41zrol4v1#
您报告进度的频率太高:
...窗口的消息循环被消息溢出,无法及时服务
CancelButton_Click
事件。