我有一些场景,我需要一个主线程等待,直到一组可能超过64个线程的每一个都完成了他们的工作,为此我写了下面的帮助器实用程序,(以避免{等待句柄的64个限制{ {1}})
WaitHandle.WaitAll()
但是,使用这个实用程序方法,每个waithandle只在数组中的每个前一个被检查后才被检查...所以它实际上是同步的,并且如果waithandles是autoResetEvent等待句柄(它清除为等待线程即将发布)
要解决此问题,我正在考虑将此代码更改为以下内容,但希望其他人检查并查看它是否可行,或者是否有人发现任何问题,或者可以提出更好的方法..
提前致谢:
public static void WaitAll(WaitHandle[] handles)
{
if (handles == null)
throw new ArgumentNullException("handles",
"WaitHandle[] handles was null");
foreach (WaitHandle wh in handles) wh.WaitOne();
}
答案 0 :(得分:3)
如果您知道有多少线程,则可以使用互锁减量。这就是我通常这样做的方式:
{
eventDone = new AutoResetEvent();
totalCount = 128;
for(0...128) {ThreadPool.QueueUserWorkItem(ThreadWorker, ...);}
}
void ThreadWorker(object state)
try
{
... work and more work
}
finally
{
int runningCount = Interlocked.Decrement(ref totalCount);
if (0 == runningCount)
{
// This is the last thread, notify the waiters
eventDone.Set();
}
}
实际上,大多数时候我甚至没有发出信号,而是调用回调继续从服务员继续进行处理。线程阻塞少,可扩展性更强。
我知道是不同的,可能不适用于你的情况(例如,如果某些thoe句柄不是线程,但I / O或事件,肯定不会工作),但它可能值得考虑这个。
答案 1 :(得分:2)
我不确定你究竟要做什么,但CountdownEvent(.NET 4.0)会从概念上解决你的问题吗?
答案 2 :(得分:1)
我不是C#或.NET程序员,但您可以使用在您的某个工作线程退出时发布的信号量。监视线程只需等待信号量 n 次,其中 n 是工作线程的数量。信号量传统上用于计算正在使用的资源,但它们可用于通过等待 n 次的相同信号量来计算完成的作业。
答案 3 :(得分:0)
当处理大量同步线程时,我更喜欢在启动线程时将每个线程的ManagedThreadId添加到Dictionary中,然后让每个线程调用一个回调例程,从而从Dictionary中删除垂死线程的id。 Dictionary的Count属性告诉您有多少个线程处于活动状态。使用键/值对的值侧保存UI线程可用于报告状态的信息。用锁包裹字典以保证安全。
答案 4 :(得分:-1)
ThreadPool.QueueUserWorkItem(o =>
{
try
{
using (var h = (o as WaitHandle))
{
if (!h.WaitOne(100000))
{
// Alert main thread of the timeout
}
}
}
finally
{
Interlocked.Decrement(ref actThreadCount);
}
}, wh);