Я работаю над инструментом, который использует BackgroundWorker для выполнения операции ping с регулярным интервалом. Я сталкиваюсь с проблемой с событием BackgroundWorker ProgressChanged. Код для ProgressChanged Event ниже:Проблема с CrossThreading с обновлением BackgroundWorker и statusstrip
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ProgressUpdated update = (ProgressUpdated)e.UserState;
if (sender.ToString() == "System.ComponentModel.BackgroundWorker")
{
toolStripStatusLabel1.Text = update.GeneralStatus;
toolStripProgressBar1.Value = update.ProgressStatus;
toolStripStatusLabel2.Text = update.SpecificStatus;
}
else
{
toolStripStatusLabel1.Text = update.GeneralStatus;
toolStripProgressBar2.Value = update.ProgressStatus;
toolStripStatusLabel3.Text = update.SpecificStatus;
}
}
событие ProgressChanged вызывается как в BackgroundWork, где он обновляет первые значения и от pingcompletedcallback случае, когда пинг заканчивается. Я только сталкиваюсь с проблемой перекрестной резьбы, когда событие ProgressChanged запускается из события PingCompletedCallback. Он выдает ошибку, когда идет обновление второй строки выполнения.
Я не могу понять, почему это происходит для одного из вызовов, но не другого.
Является ли PingCompletedCallBack происходящим в потоке BackgroundWorker, и почему он вызывает проблемы с перекрестными потоками?
Если да, то как мне поднять событие, чтобы оно обрабатывалось в потоке пользовательского интерфейса, а не на рабочем столе?
Edit:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
// creates ping and sends it async
ProgressUpdated args = new ProgressUpdated(string1, int1, string 2);
worker.ReportProgress(0,args);
// rest of thread for cleanup when cancellation is called
}
private void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
// handle the ping response
ProgressUpdated update = new ProgressUpdated(string1, int1, string2);
ProgressChangedEventArgs changed = new ProgressChangedEventArgs(1,update);
backgroundWorker1_ProgressChanged(this, changed);
// handle other types of responses
}
Я думал, что использование событий было позволить разделение потоков. Рабочий поток Aka вызывает событие, которое прослушивает поток пользовательского интерфейса, а затем возбужденное событие обрабатывается в потоке пользовательского интерфейса.
Поскольку мое понимание было неправильным, будет ли у PingCompletedCallBack доступ к методу ReportProgress для фонового рабочего?
я мог бы изменить в PingCompletedCallback:
ProgressChangedEventArgs changed = new ProgressChangedEventArgs(1,update);
backgroundWorker1_ProgressChanged(this, changed);
к:
backgroundWorker1.ReportProgress(1, update);
или мне нужно, чтобы изменить его каким-то другим способом?
Спасибо за помощь.
Edit 2:
Изменено событие ProgrssChanged
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ProgressUpdated update = (ProgressUpdated)e.UserState;
toolStripStatusLabel1.Text = update.GeneralStatus;
toolStripProgressBar1.Value = update.ProgressStatus;
toolStripStatusLabel2.Text = update.SpecificStatus;
}
Затем я создал второе событие обновления
private void PingUpdate (object sender, ProgressUpdated e)
{
toolStripStatusLabel1.Text = e.GeneralStatus;
toolStripProgressBar2.Value = e.ProgressStatus;
toolStripStatusLable3.Text = e.SepcificStatus;
}
Единственное, что у меня осталось это назвать новое событие из PingCompletedCallback в таким образом, как он выполняется в потоке пользовательского интерфейса. Является ли это, когда будет использоваться оператор Invoke или должны использоваться Invokes в новом событии?
Примечание стороны: лучше сказать "отправитель BackgroundWorker", чем sender.ToString(). Поскольку ProgressChanged выполняется в потоке пользовательского интерфейса, он не требует Invoke. –
Вам не нужно использовать какой-либо вызов в методе backgroundWorker1_ProgressChanged. Используйте ReportProgress для отчета о прогрессе, так как это именно цель этих фоновых работников; синхронизировать фоновые задачи с графическим интерфейсом. Не вызывайте backgroundWorker1_ProgressChanged (это, изменено), поскольку он будет вызван из рабочего потока. – Philippe