博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

c#的ThreadPool使用笔记(三)

Posted on 2009-06-08 20:38  sashow  阅读(1318)  评论(2编辑  收藏  举报

   很久没有接着写这个系列的东西了,自己拿起来,还有些恍惚,因为有二年多的时间没有进行代码的编写了。

 

 上次解决了如何象线程传入参数,但是没有解决在主线程中获取发生了变化的参数的问题,引起这个问题的原因有两个:

1、线程池中的线程的启动、终止不是由我们设计的程序来控制的;

2、线程池中的线程执行完成后是没有返回值的。(这实际上与操作系统的线程调度和内存分配策略有关)

所以要想取得返回值,就需要解决这两个问题。

对于第一个问题,我们很容易想到操作系统提供的一种机制 “信号灯”(也有叫“信号量”、“信号”的),操作系统提供的这种机制允许进程之间进行通讯,呵呵,这样我们就可以让子线程与主线程进行通讯了。

对于第二个问题,由于线程没有返回值,我们可以传递给线程的参数中设置一个字段用于存储返回值,也可以通过通过获取 WaitCallBack 方法所在类的属性来获取(当然,在线程中这个属性是对其进行了改变的)。

现在,简单的说一下“信号灯”机制,打一个跟厕所有关的比喻,(不是很雅^_^),在火车上,当A上厕所的时候,他会将厕所的门锁上,对外标识一个“有人”的表示,当他解决完以后,他会打开门,“有人”的标识就会变成“无人”的标识,这样B就可以进去了,而如果A不把这个标识改变,B就算憋死也进不去的。(当然暴力方式排除在外)。C# 提供的 AutoResetEvent就是这样一种“信号灯”,定义这个类的变量,并传递到子线程,在子线程将结束时,将该“信号灯”设置为 true(“无人”)状态,这样主线程就可以进入了(开始执行)。

同样,我们还有上公共厕所的经历,在公共厕所了有很多个便池,当然还有一个厕所管理员,这时,A1,A2,A3……就可以在厕所管理员这里领取一个牌匾,同时进去解决“问题”, 如果,厕所管理员不是很bt,当A1出来的时候,他会放B1进去,但是也有Bt的,非得等到A1,A2,A3……都解决问题了,才让B1,B2,……进去,这就是WaitHandle.WaitAll()和WaitHandle.WaitAny(),WaitHandle.WaitOne()的区别,这是可以使用ManualResetEvent的“信号灯”

当然,还有一些线程之间也会争用资源,要达到同步的话,可以使用Monitor,Mutex的“信号灯”。

总之,信号灯机制提供了一个对子线程与主线程,子线程与子线程之间进行通讯的机制,这些通讯机制的共同特点是某个线程释放了资源(给出一个信号),其他的线程(主线程)才开始执行。

 

接着,我用一个端口扫描的程序来具体说明一下。