2011-10-19 3 views
1

AFAIK、このイベントは作成者スレッド(BackgroundWorker RunWorkerCompleted Event)で呼び出されると約束されています。ほとんどの場合、約束どおりに行動します。ただし、RunWorkerCompletedは、BackgroundWorkerオブジェクトを作成したスレッドででなく、と呼ばれることがあります。BackgroundWorker.RunWorkerCompletedとthreading

更新:コードは次のようである:

Trace.WriteLine(Thread.CurrentThread.ManagedThreadId); 
var worker = new BackgroundWorker(); 
worker.DoWork += (s, args) => Trace.WriteLine(Thread.CurrentThread.ManagedThreadId); 
worker.RunWorkerCompleted += (s, args) => Trace.WriteLine(Thread.CurrentThread.ManagedThreadId); 
worker.RunWorkerAsync(); 

出力は1 7 7
すべてのアイデア(正しい出力は1 7 1でなければなりませんか)?

答えて

3

BackgroundWorkerはGUIアプリケーション用に設計されています。

私はあなたがコンソールアプリケーションやWinformsやWPF以外の他のタイプのアプリケーションでこれをやっていると思います。

BackgroundWorkerは、SynchronizationContext.Currentによって提供される同期モデルを使用してイベントを送出します。 GUIアプリケーションでは、SynchronizationContext.CurrentはWindowsFormsSynchronizationContextで初期化され、UIスレッドでの呼び出しによって同期が提供されます。

が非GUIアプリケーションで、SyncronizationContext.CurrentちょうどSynchronizationContextオブジェクトで、これ(from MSDN)

はない同期とフリースレッドコンテキストを提供する基本クラスです。

つまり、単にスレッドプールを介してディスパッチするので、通常は別のスレッドを毎回取得します。

winformsアプリケーションでコードを実行すると、期待どおりに動作します。

2

これはどうしてですか?

これは、バックグラウンドスレッド内にBackgroundWorkerクラスを作成した場合に発生します。

+0

ダーリンは正しいです。BackgroundWorkerを作成したスレッドで実行される主な目的は、メインのUIスレッドから作成した場合、メインのUIスレッドで実行されるため、スレッドの問題が発生することなく、イベントのUI要素と対話できます。 – Parmenion

+0

> RunWorkerCompletedは、BackgroundWorkerオブジェクト<を作成したスレッドでは呼び出されません。あなたの "答え"を書く前に質問を読む – user626528

+0

しかし、質問は:それはUIスレッドまたは既にバックグラウンドスレッドで作成されたスレッドですか?それがUIスレッドの場合、元のスレッドで呼び出されたようです。 – riezebosch

1

これは本当に古いスレッドですが、OfficeアドインでBackgroundWorker()を使用している場合は誰でもこの特定の問題にぶつかります。

ソリューションは、あなたのBackgroundWorkerを作成する前に、コードの1行を追加することです:

SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext()); 

説明はここで与えられます。

Incorrect behavior of BackgroundWorker in Office solutions

あなたはこの行を追加しない場合は、 RunWorkerCompleted()機能は、元のUIスレッドで実行されません。

(私の場合、これは私のRunWorkerCompleted()機能が私のエクセルアドインのプロジェクトにWPFのダイアログを表示することができませんでした、とSTAの例外をスローすることを意味していた。)

関連する問題