Фоновый работник не должен пытаться что-либо делать с пользовательским интерфейсом. Единственное, что может сделать поток, это уведомить тех, кто интересуется, что фоновый работник рассчитал что-то примечательное.
Это уведомление сделано с помощью Event 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, фоновый работник запускается с использованием выбранного значения. Пока фоновый работник запущен, пользователи не могут снова изменить combobox1, потому что мы не можем запустить тот же самый backgroundworker, пока он все еще занят.
Поэтому комбинированный список отключен, и отображается индикатор выполнения. Во время расчетов обновляется индикатор выполнения, а промежуточные результаты отображаются в метке 1. Когда фоновый работник завершает работу, индикатор выполнения удаляется, окончательный результат отображается в 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, индикатор выполнения исчезает, а комбинированный список снова включается:
private void OnBackgoundWorkCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.label1.Text = e.Result.ToString();
this.progressBar1.Visible = false;
this.comboBox1.Enabled = true;
}