我以前从未真正在C#中使用过线程,在C#中,我需要有两个线程以及主UI线程。基本上,我有以下几点。
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(); }
因此,本质上,我的问题是如何让一个线程等待另一个线程完成。做这个的最好方式是什么?
我可以看到5个可用选项:
和米奇的答案一样。但这会阻塞您的UI线程,但是您会为您内置一个超时。
WaitHandle
ManualResetEvent是WaitHandle克里斯蒂娜建议的。
ManualResetEvent
需要注意的一件事是,如果您要等待多个线程,WaitHandle.WaitAll()则默认情况下将不起作用,因为它需要一个MTA线程。您可以通过用Main()方法标记您的方法来解决此问题MTAThread-但这会阻塞您的消息泵,因此,根据我的阅读,不建议这样做。
WaitHandle.WaitAll()
Main()
MTAThread
请参阅乔恩·斯基特(Jon Skeet)的有关事件和多线程的页面,事件可能在if和之间取消订阅EventName(this,EventArgs.Empty)-这是我以前发生过的事情。
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); } } }
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)
我很想知道使用委托和事件进行线程通知之间的区别,我唯一知道的区别是事件是同步调用的。
这个问题的答案非常清楚地说明了使用此方法的选择。
事件/委托的处理方式将意味着您的事件处理程序 方法 位于thread1 / thread2 而非主UI线程上 ,因此您需要在HandleThreadDone方法的顶部重新切换:
// Delegate example if (InvokeRequired) { Invoke(new Action(HandleThreadDone)); return; }