如何等待多个线程停止?

8

我有一个主线程,它会产生大约20个工作线程。
我需要停止主线程直到所有其他线程都完成。
我知道(thread).Join。但那只适用于一个线程。

而且多个Joins会影响性能,如下所示。

t1.Join()
t2.Join()
...
t20.Join()

因为程序会一个接一个地等待每个线程停止。

我该如何使主线程等待一组线程全部结束呢?


5
这是期望的行为,对吗?不管它是否等待t1(而t3可能已经完成),最终当调用栈指针越过“t20.Join;”时,你知道所有线程都已停止。 - astellin
请参见https://dev59.com/QHVC5IYBdhLWcg3wihqv。 - JSBձոգչ
把线程当成糖果一样使用是一个常见的错误。只有在拥有至少20个CPU核心的机器上才启动20个线程。启动更多的线程实际上会减慢程序的运行速度。为这么多的线程正确地获取锁也非常困难,通常只会导致线程相互等待。 - Hans Passant
基本上,我需要将20个不同的文件加载到我的程序中。线程不必互动。而且我希望它可以在计算机有多少个核心的情况下都能正常工作。此外,我需要主程序等待所有20个文件都打开。 - akshaykarthik
3
如果这20个线程都是与IO相关的话,实际上同时启动它们并不会有什么问题。 - Joe White
有没有完整的源代码可用的最终解决方案?也许可以提供更复杂的示例,以便在每个线程中通知错误,并在 WaitAll 后显示摘要? - Kiquenet
5个回答

11

你应该真正了解一下任务并行(任务并行库)。它使用线程池,但还可以管理任务的窃取等。

引用:“TPL动态地扩展并发度,以最有效地使用所有可用的处理器。此外,TPL处理工作的分区、线程池上的线程调度、取消支持、状态管理和其他低级细节。”来自任务并行库

你可以这样使用它:

Task[] tasks = new Task[3]
{
    Task.Factory.StartNew(() => MethodA()),
    Task.Factory.StartNew(() => MethodB()),
    Task.Factory.StartNew(() => MethodC())
};

//Block until all tasks complete.
Task.WaitAll(tasks);

如果您使用某种循环来生成线程:

数据并行性(任务并行库)


谢谢,这正是我在寻找的。你知道这个库的任何教程吗? - akshaykarthik
这个网站:http://www.albahari.com/threading/part4.aspx 提供了关于C# 4.0最新线程特性的信息。 - Chris Laplante
@AKRamkumar 很酷 :) 嗯,没有特别的东西 :/ 猜测谷歌可以提供一些不错的东西,或者寻找一本好的 .Net Framework 4.0 或 C# 4.0 的书籍。也许这篇文章:http://msdn.microsoft.com/en-us/magazine/cc163340.aspx - Lasse Espeholt
有没有完整的源代码可用的最终解决方案?也许可以提供更复杂的示例,以便在每个线程中通知错误,并在 WaitAll 后显示摘要? - Kiquenet

4

如果你想这样做,join是可行的。但主线程仍然必须等待所有工作线程终止。请查看此网站,它是C# in a Nutshell中的一章样例。恰好是线程章节:http://www.albahari.com/threading/part4.aspx


2

我没有看到等待线程一个一个完成会产生明显的性能损失。因此,一个简单的foreach循环就可以实现您想要的功能,而不需要任何不必要的花哨东西:

foreach (Thread t in threads) t.Join();

注意:当然,有一个Win32 API函数可以同时等待几个对象(在这种情况下是线程)——WaitForMultipleObjectsEx。互联网上有许多帮助类或线程框架利用它来实现你想要的功能。但是,对于简单的情况,你真的需要它们吗?


2

多个连接会影响性能,就像这样。

如果你想等待所有线程退出,调用.join()方法即可,不会有“性能损失”。

将线程放入列表中并执行:

foreach(var t in myThread)
     t.join();

1
如果您确定始终只有不到64个线程,那么每个新线程在退出之前可可靠地设置一个事件,然后在主线程中等待所有线程的WaitAll事件。 该事件对象将在主线程中创建,并在线程创建时以线程安全的方式传递给相关的子线程。
在本机代码中,您可以在线程句柄本身上执行相同的操作,但是不确定如何在.Net中执行此操作。
还可以查看先前的问题:C#: Waiting for all threads to complete

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接