我有一些场景,需要一个主线程等待,直到一组可能超过 64 个的线程中的每一个都完成其工作,为此我编写了以下帮助程序实用程序(以避免 WaitHandle.WaitAll()
上的 64 个等待句柄限制) )
public static void WaitAll(WaitHandle[] handles)
{
if (handles == null)
throw new ArgumentNullException("handles",
"WaitHandle[] handles was null");
foreach (WaitHandle wh in handles) wh.WaitOne();
}
但是,使用此实用程序方法,仅在数组中的每个前面的等待句柄发出信号后才会检查每个等待句柄...因此它实际上是同步的,并且如果等待句柄是 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);
}
最佳答案
如果您知道有多少个线程,则可以使用互锁递减。我通常是这样做的:
{
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# - 多线程 - 等待所有线程收到信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1982572/