后台工作人员不应尝试对 UI 进行任何操作。线程唯一能做的就是通知那些感兴趣的人后台工作人员计算了一些值得注意的东西。
此通知是使用事件 ProgressChanged 完成的。
- 使用 Visual Studio Designer 创建 BackGroundWorker。
- 让设计人员为 DoWork、ProgressChanged 和 RunWorkerCompleted(如果需要)添加事件处理程序
- 如果 BackGroundWorker 想要通知表单应该显示某些内容,请使用 ProgressChanged
您可能简化了您的问题,但后台工作人员不应读取组合框的选定值。如果组合框发生变化,表单应该在传递所选组合框项的值时启动后台工作程序。
所以让我们让问题变得更有趣一点:如果用户在comboBox1 中选择了一个项目,后台工作人员会被命令使用所选的组合框值来计算一些东西。
在计算过程中,BackGroundWorker 会定期通知表单有关进度和中间计算值的信息。完成后,返回最终结果。
代码会是这样的:
private void InitializeComponent()
{
this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
this.SuspendLayout();
this.backgroundWorker1.DoWork += new DoWorkEventHandler(this.DoBackgroundWork);
this.backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(this.NotifyProgress);
this.backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
this.OnBackgounrWorkCompleted);
...
}
当一个项目被选择 comboBox1 时,后台工作程序使用选定的值启动。在后台工作程序启动时,用户无法再次更改组合框 1,因为我们无法在同一后台工作程序仍处于忙碌状态时启动它。
因此组合框被禁用,并显示一个进度条。在计算过程中,进度条会更新,中间结果显示在 Label1 中。当 backgroundworker 完成后,进度条被移除,最终结果显示在 Lable1 中并再次启用组合框。
请注意,当后台工作人员正在计算时,表单的其余部分仍在工作。
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox comboBox = (ComboBox)sender;
// disable ComboBox, show ProgressBar:
comboBox.Enabled = false;
this.progressBar1.Minimum = 0;
this.progressBar1.Maximum = 100;
this.progressBar1.Value = 0;
this.progressBar1.Visible = true;
// start the backgroundworker using the selected value:
this.backgroundWorker1.RunWorkerAsync(comboBox.SelectedValue);
}
后台工作:
private void DoBackgroundWork(object sender, DoWorkEventArgs e)
{
// e.Argument contains the selected value of the combobox
string test = ((KeyValuePair<string, string>)e.Argument;
// let's do some lengthy processing:
for (int i=0; i<10; ++i)
{
string intermediateText = Calculate(test, i);
// notify about progress: use a percentage and intermediateText
this.backgroundWorker1.ReportProgress(10*i, intermediateText);
}
string finalText = Calculate(test, 10);
// the result of the background work is finalText
e.Result = finalText;
}
您的表单会定期收到有关进度的通知:让它更新 ProgressBar 并在 Label1 中显示中间文本
private void NotifyProgress(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Value = e.ProgressPercentage;
this.label1.Text = e.UserState.ToString();
}
BackgroundWorker 完成后,最终文本显示在 label1 中,进度条消失,再次启用 Combobox:
private void OnBackgoundWorkCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.label1.Text = e.Result.ToString();
this.progressBar1.Visible = false;
this.comboBox1.Enabled = true;
}