私はBackgroundWorkerを使用して一定の間隔でping操作を実行するツールを開発しています。 BackgroundWorker ProgressChangedイベントに関する問題が発生しています。 ProgressChangedイベントのコードは、以下である:pingが終了したときBackgroundWorkerとstatusstrip updateでのクロススレッドの問題
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イベントから実行されるときにのみ、クロススレッドの問題に遭遇します。 2番目の進捗バーを更新すると、エラーがスローされます。
私はなぜコールの1つではなく、他のもので起こっているのか理解できないようです。
BackgroundWorkerスレッドでPingCompletedCallBackが起きているのですが、それが原因でクロススレッドの問題が発生するのはなぜですか?
もしそうなら、イベントを発生させて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
}
私はイベントの使用は、スレッドの分離を可能にすることだと思いました。別名ワーカースレッドは、UIスレッドがリッスンしているイベントを発生させ、発生したイベントはUIスレッドで処理されます。
私の理解が間違っていたため、PingCompletedCallBackはバックグラウンドワーカーのReportProgressメソッドにアクセスできますか?
私はその後PingCompletedCallbackに変更することができます:
ProgressChangedEventArgs changed = new ProgressChangedEventArgs(1,update);
backgroundWorker1_ProgressChanged(this, changed);
へ:
backgroundWorker1.ReportProgress(1, update);
または私はいくつかの他の方法でそれを変更する必要があるでしょうか?
ありがとうございました。
編集2:
私は、私は残っている唯一のことはしてPingCompletedCallbackから新しいイベントを呼び出すことです
private void PingUpdate (object sender, ProgressUpdated e)
{
toolStripStatusLabel1.Text = e.GeneralStatus;
toolStripProgressBar2.Value = e.ProgressStatus;
toolStripStatusLable3.Text = e.SepcificStatus;
}
第2の更新イベントを作成し
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;
}
変更ProgrssChangedイベントUIスレッドで実行されるような方法です。 Invokeステートメントを使用する場所か、新しいイベントでInvokeを使用する必要がありますか?
サイドノート:)sender.ToStringより( "送信者がBackgroundWorkerのである" と言った方が良いです。 ProgressChangedはUIスレッドで実行されるため、Invokeは必要ありません。 –
backgroundWorker1_ProgressChangedメソッドで何らかの呼び出しを使用する必要はありません。 ReportProgressを使用して進捗状況を報告します。これは、これらのバックグラウンドワーカーの目標です。バックグラウンドタスクをGUIと同期させる。ワーカースレッドから呼び出されるため、backgroundWorker1_ProgressChanged(これは変更されたもの)を呼び出さないでください。 – Philippe