多线程 - 等待所有线程发信号
我有一些场景,我需要一个主线程来等待一组可能超过64个线程的每一个都完成了他们的工作,为此我写了以下帮助程序效用,(以避免上WaitHandle.WaitAll()
64 WaitHandle的极限)多线程 - 等待所有线程发信号
public static void WaitAll(WaitHandle[] handles)
{
if (handles == null)
throw new ArgumentNullException("handles",
"WaitHandle[] handles was null");
foreach (WaitHandle wh in handles) wh.WaitOne();
}
在此实用程序的方法,但是,每个WaitHandle中只检查后每前一个阵列中的已用信号通知...所以它实际上是同步,并且如果等待句柄是autoResetEvent等待句柄(一旦等待线程被释放,它就会清除)将不起作用
要解决此问题,我正在考虑将此代码更改为以下内容,但希望其他人检查并查看它是否会起作用,或者如果有人看到任何问题,或者可以提供更好的方法......
在此先感谢:
public static void WaitAllParallel(WaitHandle[] handles)
{
if (handles == null)
throw new ArgumentNullException("handles",
"WaitHandle[] handles was null");
int actThreadCount = handles.Length;
object locker = new object();
foreach (WaitHandle wh in handles)
{
WaitHandle qwH = wh;
ThreadPool.QueueUserWorkItem(
delegate
{
try { qwH.WaitOne(); }
finally { lock(locker) --actThreadCount; }
});
}
while (actThreadCount > 0) Thread.Sleep(80);
}
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);
'qwH'在循环中被本地声明,所以这不是问题。 – dtb 2009-12-30 21:39:34
如果您知道您有多少个线程,则可以使用互锁递减。这就是我通常做:
{
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();
}
}
其实,大多数时候,我甚至不发出信号,而是调用回调继续从那里服务员会继续处理。阻塞线程少,可扩展性好。
我知道是不同的,可能不适用于你的情况(例如,如果某些句柄不是线程,但I/O或事件肯定不会工作),但它可能值得考虑。
我不是C#或.NET程序员,但可以使用当您的其中一个工作线程退出时发布的信号量。监视线程将简单地等待信号量n次,其中n是工作线程的数量。信号量传统上用于统计正在使用的资源,但它们可用于计算通过等待n次相同信号量完成的工作。
在处理大量并发线程时,我更愿意在启动线程时将每个线程的ManagedThreadId添加到字典中,然后让每个线程调用一个回调例程,以从Dictionary中删除垂死线程的ID。 Dictionary的Count属性告诉你有多少线程处于活动状态。使用键/值对的值侧来保存您的UI线程可用于报告状态的信息。使用锁包装词典以保持安全。
您确定您需要64+个主题?这味道稍微IMHO。 – dtb 2009-12-30 21:33:59
您是否可以进一步解释如何以及为什么使用AutoResetEvent?工作完成后线程是否结束? – dtb 2009-12-30 21:36:32
而不是锁定对象,为什么不使用Interlocked(http://msdn.microsoft.com/en-us/library/system.threading.interlocked.aspx)类来增加和减少活动工作器的数量? – 2009-12-30 21:40:54