2012-05-03 9 views
0

私はこのようなものが含まれている[STAThread]メインを持っています。バックグラウンド作業は、次のように初期化される:今クロススレッドの問題は、BackgroundWorkerのとReportProgress

MyBackgroundWorker = new BackgroundWorker(); 
MyBackgroundWorker.WorkerSupportsCancellation = true; 
MyBackgroundWorker.WorkerReportsProgress = true; 
MyBackgroundWorker.DoWork +=new DoWorkEventHandler(MyBackgroundWorker_DoWork); 
MyBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(MyBackgroundWorker_ProgressChanged); 
MyBackgroundWorker.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(MyBackgroundWorker_RunWorkerCompleted); 
MyBackgroundWorker.RunWorkerAsync(); 

、バックメインフォーム(TopViewFormのインスタンス)への進捗状況を報告するために、列挙子のスレッドがいくつかの適切なユーザーオブジェクトとReportProgressを呼んでいます。 ReportProgressは、ProgressChangedイベントの形で到着し、Enumerator自体が作成されたスレッド(つまり、BackgroundWorkerのスレッドではない)であるメインのUIスレッドで実行されます。

この場合、このオブジェクトのイベントに応答して、メインプロセススレッド上のノードをTreeViewに設定しようとすると、クロススレッド違反エラーが発生する可能性はありますか? ProgressChangedは、がメインプロセススレッド上で実行されているように見えず、コールスタックを見ています。

私は、Application.Runが新しいスレッドを生成し、そのフォームを実行すると仮定します。しかし、ドキュメンテーションはそうでないと言います。私は愚かな誤りを犯したか、ここで私が理解できない何かがあります。

誰もが考えていますか?

+0

BgwはApplication.Run()と密接に連携しているため、フォームの内部に移動します。 –

+0

あなたの両方の良い考え。私がフォーム内で移動すると、正常に動作します。 – Robinson

+0

さて、答えとして追加する最初のものは、ポイントを取得します:) – Robinson

答えて

2

BackgroundWorkerは、機能するために設定されている現在のSynchronizationContextに依存しています。 ProgressChangedイベントはSendOrPostCallback Delegateとして実装され、msdnドキュメントに記載されています。SendOrPostCallbackは、メッセージを同期コンテキストにディスパッチするときに実行するコールバックメソッドを表します。フォームデザイナーのフォームにBackgroundWorkerを追加すると、SynchronizationContextが正しく設定されます。あなたのケースでは、BackgroundWorkerにはSynchronizationContextが割り当てられていません。

+0

ああ、これは実際の正解です。 info volodyありがとう。 – Robinson

3

Application.Runが最初に呼び出される前に、進行状況変更イベントが実行されていると思います。 Mainからバックグラウンドワーカーを起動するのではなく、フォームの中からバックグラウンドワーカーを開始する場合は、バックグラウンドワーカーが作成され、進行状況の報告を開始するときにメッセージループが既に存在していることを確認してください。