私は利用可能な5つのオプションを見ることができます:
1. Thread.Join
ミッチの答えと同じです。しかし、これによりUIスレッドがブロックされますが、タイムアウトが組み込まれます。
2.を使用 WaitHandle
ManualResetEvent
WaitHandle
jristaが提案するとおりです。
WaitHandle.WaitAll()
MTAスレッドが必要なため、複数のスレッドを待機したい場合、デフォルトでは機能しないことに注意してください。Main()
メソッドにマークを付けることでこれを回避できますが、これMTAThread
はメッセージポンプをブロックするため、私が読んだことからはお勧めできません。
3.イベントを発生させる
イベントとマルチスレッドについてJon Skeetによるこのページを参照してください。イベントは、if
との間でサブスクライブ解除される可能性がありますEventName(this,EventArgs.Empty)
-以前に発生しました。
(うまくいけば、これらはコンパイルされ、私は試していません)
public class Form1 : Form
{
int _count;
void ButtonClick(object sender, EventArgs e)
{
ThreadWorker worker = new ThreadWorker();
worker.ThreadDone += HandleThreadDone;
Thread thread1 = new Thread(worker.Run);
thread1.Start();
_count = 1;
}
void HandleThreadDone(object sender, EventArgs e)
{
// You should get the idea this is just an example
if (_count == 1)
{
ThreadWorker worker = new ThreadWorker();
worker.ThreadDone += HandleThreadDone;
Thread thread2 = new Thread(worker.Run);
thread2.Start();
_count++;
}
}
class ThreadWorker
{
public event EventHandler ThreadDone;
public void Run()
{
// Do a task
if (ThreadDone != null)
ThreadDone(this, EventArgs.Empty);
}
}
}
4.デリゲートを使用する
public class Form1 : Form
{
int _count;
void ButtonClick(object sender, EventArgs e)
{
ThreadWorker worker = new ThreadWorker();
Thread thread1 = new Thread(worker.Run);
thread1.Start(HandleThreadDone);
_count = 1;
}
void HandleThreadDone()
{
// As before - just a simple example
if (_count == 1)
{
ThreadWorker worker = new ThreadWorker();
Thread thread2 = new Thread(worker.Run);
thread2.Start(HandleThreadDone);
_count++;
}
}
class ThreadWorker
{
// Switch to your favourite Action<T> or Func<T>
public void Run(object state)
{
// Do a task
Action completeAction = (Action)state;
completeAction.Invoke();
}
}
}
_countメソッドを使用する場合は、(安全のため)を使用してインクリメントすることをお勧めします
Interlocked.Increment(ref _count)
スレッド通知にデリゲートとイベントを使用する違いを知りたいのですが、イベントが同期的に呼び出されることだけが違います。
5.代わりに非同期で行う
この質問に対する答えには、この方法でのオプションの非常に明確な説明があります。
間違ったスレッドのデリゲート/イベント
イベント/デリゲートの方法は、イベントハンドラーメソッドがメインのUIスレッドではなく thread1 / thread2にあることを意味します。そのため、HandleThreadDoneメソッドの最上部で元に戻す必要があります。
// Delegate example
if (InvokeRequired)
{
Invoke(new Action(HandleThreadDone));
return;
}