如何等待线程完成.NET?
我以前从未真正在C#中使用过线程,在C#中,我需要有两个线程以及主UI线程。基本上,我有以下内容。
I've never really used threading before in C# where I need to have two threads, as well as the main UI thread. Basically, I have the following.
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();
}
因此,从本质上讲,我如何让一个线程等待另一个线程完成?最好的方法是什么?
So, essentially, how can I have a thread wait for another one to finish? What is the best way to do this?
我可以看到五个可用的选项:
I can see five options available:
与Mitch的答案一样。但这会阻塞您的UI线程,但是会为您内置一个超时。
As with Mitch's answer. But this will block your UI thread, however you get a Timeout built in for you.
ManualResetEvent
是 WaitHandle 建议使用
。
ManualResetEvent
is a WaitHandle
as jrista suggested.
要注意的一件事是,是否要等待多个线程: WaitHandle.WaitAll()
默认情况下将不起作用,因为它需要一个 MTA 线程。您可以通过使用 MTAThread
标记您的 Main()
方法来解决此问题-但是,这会阻止您的消息泵,并且不会
One thing to note is if you want to wait for multiple threads: WaitHandle.WaitAll()
won't work by default, as it needs an MTA thread. You can get around this by marking your Main()
method with MTAThread
- however this blocks your message pump and isn't recommended from what I've read.
请参见此页的作者Jon Skeet 关于事件和多线程。 if
和 EventName(this,EventArgs.Empty)
之间的事件可能会取消订阅-发生了
See this page by Jon Skeet about events and multi-threading. It's possible that an event can become unsubcribed between the if
and the EventName(this,EventArgs.Empty)
- it's happened to me before.
(希望这些编译,我没有尝试过)
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方法,则可能是一个想法(为了安全起见)使用
If you do use the _count method, it might be an idea (to be safe) to increment it using
Interlocked.Increment(ref _count)
我想知道使用委托和事件进行线程通知之间的区别,我所知道的唯一区别是事件被同步调用。
I'd be interested to know the difference between using delegates and events for thread notification, the only difference I know are events are called synchronously.
此问题的答案使用此方法对选项进行了非常清晰的描述。
The answer to this question has a very clear description of your options with this method.
事件/委托的处理方式将意味着您的事件处理程序方法位于线程1 /线程2 上而不是主UI线程上,因此您需要向右切换在HandleThreadDone方法的顶部:
The event/delegate way of doing things will mean your event handler method is on thread1/thread2 not the main UI thread, so you will need to switch back right at the top of the HandleThreadDone methods:
// Delegate example
if (InvokeRequired)
{
Invoke(new Action(HandleThreadDone));
return;
}