私はこれまで、メイン UI スレッドに加えて 2 つのスレッドが必要な C# でスレッド処理を実際に使用したことはありませんでした。基本的には、次のようになります。
public void StartTheActions()
{
// Starting thread 1....
Thread t1 = new Thread(new ThreadStart(action1));
t1.Start();
// Now, I want for the main thread (which is calling `StartTheActions` method)
// to wait for `t1` to finish. I've created an event in `action1` for this.
// The I wish `t2` to start...
Thread t2 = new Thread(new ThreadStart(action2));
t2.Start();
}
では、本質的に、別のスレッドが終了するまでスレッドを待機させるにはどうすればよいのでしょうか? これを実行する最善の方法は何でしょうか?
ベストアンサー1
利用可能なオプションは 5 つあります。
1. スレッド結合
Mitch の回答と同じです。ただし、これにより UI スレッドがブロックされますが、タイムアウトが組み込まれます。
2. 使用するWaitHandle
ManualResetEvent
jrista が示唆したとおりですWaitHandle
。
注意すべき点は、複数のスレッドを待機したい場合、WaitHandle.WaitAll()
デフォルトでは動作しないということです。インド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. 代わりに非同期で実行する
答えはこの質問この方法のオプションについて非常に明確に説明されています。
間違ったスレッドのデリゲート/イベント
イベント/デリゲート方式では、イベントハンドラは方法スレッド1/スレッド2にありますメインUIスレッドではないそのため、HandleThreadDone メソッドの先頭で切り替える必要があります。
// Delegate example
if (InvokeRequired)
{
Invoke(new Action(HandleThreadDone));
return;
}