我一直在研究一种使用 BackgroundWorker 定期执行 ping 操作的工具。我遇到了 BackgroundWorker ProgressChanged 事件的问题。ProgressChanged 事件的代码如下:
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 中调用,在 ping 完成时从 pingcompletedcallback 事件中调用。当 ProgressChanged 事件从 PingCompletedCallback 事件运行时,我只遇到了跨线程问题。它在更新第二个进度条时抛出错误。
我似乎无法弄清楚为什么其中一个电话会发生这种情况,而另一个电话不会。
PingCompletedCallBack 是否发生在 BackgroundWorker 线程上,这就是它导致跨线程问题的原因?
如果是这样,我如何引发事件以便在 UI 线程而不是后台工作人员上处理它?
编辑:
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 工作线程引发 UI 线程正在侦听的事件,然后在 UI 线程上处理引发的事件。
由于我的理解是错误的,PingCompletedCallBack 是否可以访问后台工作程序的 ReportProgress 方法?
然后我可以更改 PingCompletedCallback:
ProgressChangedEventArgs changed = new ProgressChangedEventArgs(1,update);
backgroundWorker1_ProgressChanged(this, changed);
到:
backgroundWorker1.ReportProgress(1, update);
还是我需要以其他方式更改它?
感谢任何人的帮助。
编辑2:
Changed 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 调用新事件,使其在 UI 线程上执行。这是使用 Invoke 语句的地方还是应该在新事件中使用 Invoke?