2009-02-27 43 views
3

2つのスレッドを開始する1つのメインスレッドがある場合。 プライマリスレッドが2つの他のスレッドを待つ最もクリーンな方法は何ですか?2つのスレッドが終了するのを待ちます。

私はbgndworkerとsleep spinnerを使用して、両方のbgndワーカーのIsBusyをチェックできますが、より良い方法があると思います。

EDIT いくつかのより多くの要件:

  • メインスレッドが(例えばGUI)を行うには、いくつかの他の仕事を持っています。
  • 2つの生み出されたスレッドが例外を報告することができ、その結果がWaitHandle.WaitAnyはあなたの友達です
+0

も参照してください:http://stackoverflow.com/questions/540078/wait-for-pooled-threads-to-complete –

答えて

5

this threadの回答を参照してください。私はthis option ;-p

Forker p = new Forker(); 
p.Fork(delegate { DoSomeWork(); }); 
p.Fork(delegate { DoSomeOtherWork(); }); 
p.Join(); 

再値/レポーティングの例外を返すが好き - ちょうど、それぞれのフォークを持っているロジックの最後にコールバックとしてというか...(あなたが両方に状態を渡すために撮影した変数を使用することができますフォーク、共有ロガーなどを含む)。

0

値を返す必要があります。これにより、複数のスレッドやその他の種類のオブジェクトが通知されるのを待つことができます。

http://msdn.microsoft.com/en-us/library/tdykks7z.aspx

EDIT:

は実際には、WaitHandle.WaitAllはあなたが望むものではなく、WAITANY。

http://msdn.microsoft.com/en-us/library/system.threading.waithandle.waitall.aspx

EDIT:

参加方法いくつかの言及はOKですが、一つの欠点は、それが完全にアトミック操作ではないということです。しかし、これはあなたにとって重要かもしれません。

+0

私の現在の状況ではそれほど重要ではありませんが、私は主なアイデアを得ようとしますすべての質問のうち、私は後で他の問題が発生したときにそれを適用することができます。そう、はい、それは何らかの形で重要です。 –

3
thread1.Join(); 
thread2.Join(); 
+0

これはバニラのスレッドを必要とし、例外などのバブルを許可しません。 –

+3

"追加の要件"を追加する前はすばらしい答えでした。彼はユーザーでなければなりません... –

+0

はい - おそらく2番目の質問は適切でしょう –

10

Thread.Join();を使用した簡単な例。

 Thread t1 = new Thread(new ThreadStart(delegate() 
     { 
      System.Threading.Thread.Sleep(2000); 
     })); 

     Thread t2 = new Thread(new ThreadStart(delegate() 
     { 
      System.Threading.Thread.Sleep(4000); 
     })); 

     t1.Start(); 
     t2.Start(); 

     t1.Join(); 
     t2.Join(); 

EDITは待ちを使用して別の3exampleは、ハンドル:は、他の回答に加えて

  ManualResetEvent[] waitHandles = new ManualResetEvent[]{ 
      new ManualResetEvent(false), 
      new ManualResetEvent(false) 
     }; 

     Thread t1 = new Thread(new ParameterizedThreadStart(delegate(object state) 
     { 
      ManualResetEvent handle = (ManualResetEvent)state; 
      System.Threading.Thread.Sleep(2000); 
      handle.Set(); 
     })); 

     Thread t2 = new Thread(new ParameterizedThreadStart(delegate(object state) 
     { 
      ManualResetEvent handle = (ManualResetEvent)state; 
      System.Threading.Thread.Sleep(4000); 
      handle.Set(); 
     })); 

     t1.Start(waitHandles[0]); 
     t2.Start(waitHandles[1]); 

     WaitHandle.WaitAll(waitHandles); 

     Console.WriteLine("Finished"); 
+0

2番目の執行は私を助けてくれるでしょう、私はそれを見てみましょう –

+0

backgroundworkerとreseteventsを使用する方法はありますか? –

+0

BackgroundWorkerのRunWorkerCompletedを購読する。タスクが完了、キャンセル、または例外が発生したときに起動される。 –

1

...「二つのスレッドを起動して、両方が終了するのを待つ」する一つの選択肢がある「を開始します1つのスレッドと自分で1つの仕事をし、その後、他のスレッドが完了するのを待つ "。

もちろん、2つのジョブを開始したい場合は、メインスレッドでもう少し作業をしてください。そして、は他の2つのスレッドが完了するのを待っています。

EDIT:メインスレッドがUIスレッドの場合、終了した他のスレッドをブロックしてはいけません。終了したらメインスレッドにコールバックする必要があります。そうすることで、実行中に応答しやすいUIが得られます。

+0

はい、有効なポイントです。しかし、たぶん私はその質問を単純化しました。メインスレッドはUIの更新に忙しいので、IOの重いタスクに煩わされることはありません。 –

+0

メインスレッドはコンソールスレッドです。何度か繰り返して "Waiting ..."というメッセージが表示されます。しかし、私は紡ぎ上がりの出来事についてあなたに従います。私の他の質問を参照してください:http://stackoverflow.com/questions/594329/define-backgroundworkers-runworkercompleted-with-an-anonymous-methodまたは私は完全にオフトラックですか? –

1

終了を待ってGUIを使用することはできません。このための最良の方法は、スレッドを生成してイベントを使用してGUIと通信することです。イベントハンドラでは、コントロールを変更できないことに注意してください。代わりに、直接Invokeメソッドを使用します。

+0

通常、スレッドに自閉症をさせたくない場合は、進捗情報のイベントの使用を避けることができないように、GUIに戻る情報も必要です。この回答は、私がこのページで読むことができた最高のものです! – jdehaan

関連する問題