最近在用Net写程序时遇到一个问题有N个互不相关的任务要在线程池中跑但有一个线程要等待N个任务完成之后才能继续而这个N是个未知数可能会 很大(因此才会想到使用线程池而不是手动去new一个therad)翻了翻Net类库的文档发现一个叫WaitHandle的类这个类的用法挺有 意思需要为每个线程创建一个WaitHandle对象并把它们放在一个数组中然后用WaitHandle类中的WaitAll方法来等待这些 WaitHandle被调用Set方法(代码就不写了可以参考MSDN http://msdnmicrosoftcom/zhcn/library /systemthreadingwaithandleaspx)
虽然觉得这有点复杂但还是试了试当程序运行时碰到了一个问 题如果WaitHandle数组超过个元素之后WaitHandle对象的WatiAll方法罢工了后来为了程序能运行只得想了一个笨办法 先创建两个WaitHandle对象放在数组然后用循环两个两个地运行任务代码的思路大概是下面这样
WaitHandle[] handles = new WaitHandle[]{
new AutoResetEvent(false)
new AutoResetEvent(false)
};
int times = (int)N/;
int i;
for(i = ; i < times; i++){
ThreadPoolQueueUserWorkItem(new WaitCallback(Tasks[i*]) handles[]);
ThreadPoolQueueUserWorkItem(new WaitCallback(Tasks[i*+]) handles[]);
WaitHandleWaitAll(handles);
}
if(i* < N){
ThreadPoolQueueUserWorkItem(new WaitCallback(Tasks[i* + ]) handles[]);
WaitHandleWaitAny(handles);
}
虽然代码这么写比较复杂但至少可以保证运行时不会出问题但这么写代码显然并不KISS!于是问了问高手说有个 RegisterWaitForSingleObject方法但一看这个方法的参数列表就够让人晕的了有点怀念Java了记得Java中有个 CountDownLatch类创建类的时候赋一个初始值X然后主线程中调用await线程池中跑的线程调用countDown方法就可以实现主 线程等待X次countDown方法调用之后继续这样既没有个WaitHandle的限制也不用去研究那个 RegisterWaitForSingleObject方法不过问题在于Net中并没有这么一个东西只能自己动手了
class CountDownLatch {
private object lockobj;
private int counts;
public CountDownLatch(int counts){
thiscounts = counts;
}
public void Await(){
lock(lockobj){
while(counts > ){
MonitorWait(lockobj);
}
}
}
public void CountDown(){
lock(lockobj){
counts;
MonitorPulseAll(lockobj);
}
}
}
有了这个东西上面的代码可以改的更少一些
CountDownLatch cdl = new CountDownLatch(N);
for(int i = ; i < N; i++){
ThreadPoolQueueUserWorkItem(new WaitCallback(Tasks[i]) cdl);
}
cdlAwati();
而对于任务的代码来说在结尾处吧对WaitHandle的Set方法的调用改为对CountDownLatch类的CountDown方法的调用即可
最后我想说的是其实没必要把思路都拘束在Net上或者Java上相互借鑒会让思路更开阔一些不过有句心里话想说的就是其实Java的类库在某些方面做的比Net好一些