当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > ASP.NET教程:WaitHandle类

ASP.NET
赫赫大名的A*寻路算法(vb.net版本)
asp.net(c#)下Jmai去说明 使用与下载
[原创]完美解决Could not load file or assembly ''AjaxPro.2'' or one of its dependencies. 拒绝访问。
asp.net下gridview 批量删除的实现方法
用CSS实现图片倾斜 只支持IE
.net get set用法小结
vs 不显示行号的操作方法
ASP.NET页面进行GZIP压缩优化的几款压缩模块的使用简介及应用测试!(附源码)
ASP.Net不执行问题一解
asp.net 无限分类
让VS2008对JQuery语法的智能感知更完美一点
扩展方法ToJSON() and ParseJSON()
asp.net下PageMethods使用技巧
Linq to SQL Delete时遇到问题的解决方法
实现ASP.NET多文件上传程序代码
ASP.NET AJAX 1.0 RC开发10分钟图解
asp.net get set用法
ASP.NET下使用WScript.Shell执行命令
asp.net2.0实现邮件发送(测试成功)
Asp.net 无限级分类实例代码

ASP.NET教程:WaitHandle类


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-28   浏览: 62 ::
收藏到网摘: n/a

最近笔者在用.Net写程序时遇到一个问题:有N个互不相关的任务要在线程池中跑,但有一个线程要等待N个任务完成之后才能继续。而这个N是个未知数,可能会 很大(因此才会想到使用线程池而不是手动去new一个therad)。翻了翻.Net类库的文档,发现一个叫WaitHandle的类。这个类的用法挺有 意思,需要为每个线程创建一个WaitHandle对象并把它们放在一个数组中,然后用WaitHandle类中的WaitAll方法来等待这些 WaitHandle被调用Set方法。(代码就不写了,可以参考MSDN http://msdn.microsoft.com/zh-cn/library /system.threading.waithandle.aspx)

虽然觉得这有点复杂,但还是试了试。当程序运行时,碰到了一个问 题,如果WaitHandle数组超过64个元素之后,WaitHandle对象的WatiAll方法罢工了。后来为了程序能运行,只得想了一个笨办法: 先创建两个WaitHandle对象放在数组,然后用循环两个两个地运行任务。代码的思路大概是下面这样:

WaitHandle[] handles = new WaitHandle[]{
new AutoResetEvent(false),
new AutoResetEvent(false)
};
int times = (int)N/2;
int i;
for(i = 0; i < times; i++){
ThreadPool.QueueUserWorkItem(new WaitCallback(Tasks[i*2]), handles[0]);  
ThreadPool.QueueUserWorkItem(new WaitCallback(Tasks[i*2+1]), handles[1]);
WaitHandle.WaitAll(handles);
}
if(i*2 < N){
ThreadPool.QueueUserWorkItem(new WaitCallback(Tasks[i*2 + 1]), handles[0]);
WaitHandle.WaitAny(handles);
}

虽然代码这么写比较复杂,但至少可以保证运行时不会出问题。但这么写代码显然并不KISS!于是问了问高手,说有个 RegisterWaitForSingleObject方法,但一看这个方法的参数列表就够让人晕的了。有点怀念Java了,记得Java中有个 CountDownLatch类,创建类的时候赋一个初始值X,然后主线程中调用await,线程池中跑的线程调用countDown方法。就可以实现主 线程等待X次countDown方法调用之后继续。这样既没有64个WaitHandle的限制,也不用去研究那个 RegisterWaitForSingleObject方法。不过问题在于.Net中并没有这么一个东西,只能自己动手了。

class CountDownLatch {
private object lockobj;
private int counts;

 

public CountDownLatch(int counts){
this.counts = counts;
}

public void Await(){
lock(lockobj){
while(counts > 0){
Monitor.Wait(lockobj);
}
}
}

public void CountDown(){
lock(lockobj){
counts--;
Monitor.PulseAll(lockobj);
}
}
}

有了这个东西,上面的代码可以改的更少一些。


CountDownLatch cdl = new CountDownLatch(N);
for(int i = 0; i < N; i++){
ThreadPool.QueueUserWorkItem(new WaitCallback(Tasks[i]), cdl);
}
cdl.Awati();

而对于任务的代码来说,在结尾处吧对WaitHandle的Set方法的调用改为对CountDownLatch类的CountDown方法的调用即可。
最后,我想说的是其实没必要把思路都拘束在.Net上或者Java上,相互借鉴会让思路更开阔一些。

不过有句心里话想说的就是,其实Java的类库在某些方面做的比.Net好一些。