最近在用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好一些
From:http://tw.wingwit.com/Article/program/net/201311/15545.html