我可以看到五个可用选项:
1。线程.Join
与米奇的回答一样。但这会阻塞你的 UI 线程,但是你会得到一个内置的 Timeout。
2。使用WaitHandle
ManualResetEvent 是 jrista 建议的 WaitHandle。
需要注意的一点是,如果你想等待多个线程:WaitHandle.WaitAll() 默认不会工作,因为它需要一个MTA 线程。您可以通过使用 MTAThread 标记您的 Main() 方法来解决此问题 - 但是这会阻止您的消息泵,并且不推荐从我所阅读的内容。
3。触发事件
请参阅this page by 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。改为异步执行
this question 的答案非常清楚地描述了您使用此方法的选项。
错误线程上的委托/事件
事件/委托的处理方式意味着您的事件处理程序方法在线程 1/线程2 不是主 UI 线程,因此您需要向右切换在 HandleThreadDone 方法的顶部:
// Delegate example
if (InvokeRequired)
{
Invoke(new Action(HandleThreadDone));
return;
}