我可以看到5个可用选项:
1. Thread.Join
与米奇的答案一样。但这会阻塞您的UI线程,但是您会为您内置一个超时。
2.使用 WaitHandle
ManualResetEvent
是WaitHandle
克里斯蒂娜建议的。
需要注意的一件事是,如果您要等待多个线程,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.异步执行
这个问题的答案非常清楚地说明了使用此方法的选择。
代表/事件在错误的线程上
事件/委托的处理方式将意味着您的事件处理程序方法位于thread1 / thread2 而非主UI线程上,因此您需要在HandleThreadDone方法的顶部重新切换:
// Delegate example
if (InvokeRequired)
{
Invoke(new Action(HandleThreadDone));
return;
}