我来谈一谈线程

来源:互联网 发布:程序员屏幕多大 编辑:程序博客网 时间:2024/06/11 14:02
 

   我坚信每个程序员都有被线程折磨得死去活来的经历,我也是!为了解决一个问题,我愣是弄了两天,发帖求助,但是最终也没有解决!没有办法只有自己动手,丰衣足食!

     上面是一点废话,其实,线程我也没有弄透彻,今天只是写一写其两个属性,Terminated, Suspended,不要小看这两个属性,它们确实管理TThread子类的重要开关。下面开始正题:

    1. 简单介绍Suspended、Terminated。

     Suspended:这个属性我们在构造函数中见到,创建一个继承自TThread的类的对象的时候,我们往往会考虑,这个类要不要先suspend,设置完相关属性之后,我们再唤醒Resume。其他的时候,好像也没怎么关注(ps:当然作为熟练掌握线程的人来说,看到我说这句话肯定会鄙视我:只有你自己没有关注而已吧 ...我承认!),但是这个属性相当的重要?为什么?且看下面介绍Termianted。

     Terminated:首先说明这是一个只读的属性,而且在TThread中是公布在Protected中,因此,当一个继承自TThread的子类被当做另外一个类的类变量的时候,我们就无法访问了这个属性了,不过没有关系啊,我们完全可以在TThread的继承类中public一下,这样会不会破坏封装性?安全性?个人觉得,作为一个只读属性,这个应当无大碍!这个属性值为True的时候,Suspended也会置为True。一个线程被标记为Terminated的时候,这个线程也就标志着废了,要想跑起来(Execute里面的代码),这时候应该这样做:做好这个线程的收尾工作,对于收尾工作,可以这样做:在创建线程对象的时候,设置FreeOnTerminate这个属性值为True,另外如果在收尾的时候想跟主线程交互的话,那么可以写一个跟TNotifyEvent格式相同的方法,将方法指针赋值给OnTerminate,同时,如果在创建线程对象的时候显式的创建了对象,那么可以将这部分放到线程类的析构中,这样一般就没有什么问题了,用FastMM检测,就不应该有内存泄露了,做完收尾工作之后,就创建新的线程对象,并让其处于唤醒状态,这样线程对象就会正常的工作了。

    2.终止线程的时候调用类似 AThread.Terminate就万事大吉?    其实不是的。举一个例子 

     AThread := ASampleThread.Create(True);

     AThread.Terminate;

   这样是有问题的!原因在于AThread.Suspended = True; 一个线程如果处在Suspended的状态的时候,调用Terminate就会出问题。那么这种情况怎么办呢?我的解决办法有点暴力,不过或许只能这样做吧:

if Assigned(FThread) and (not FThread.Terminated) thenbegin
  if FThread.Suspended then    FThread.Resume;  FThread.Terminate;end;     

    3  FreeOnTerminate在释放线程资源的时候,真的只是Free没有nil!

    如果你的类A中有一个线程类变量(ATrhead),而且AThread的FreeOnTerminate设置为True,在析构你的类的时候,你特别的加上一句FreeAndNil(AThread),那么这时候系统会提示你尝试修改已经释放的内存,原因就是FreeOnTerminate做的工作是Free而不是FreeAndNil,调用两遍FreeAndNil当然没有问题,但是调用两次Free就是有问题的,那么在什么地方设置AThread := nil呢?可以放在赋值给OnTerminate的函数中,这样就真的安全了。

   4. 如果线程对象的Execute执行完成之后,线程对象的状态是怎样的呢?

   Suspended = Terminated = True.其实不严格的话,也可以说成线程Sleep了,不过这个Sleep是无法唤醒的,因为该线程对象被终结了!所以,这样看来,由于Suspended是一个可写可读的变量,因此,你有可能这样赋值 AThread.Suspended := False;或者AThread.Resume.但是如果AThread的Terminated为True,那么这样做肯定是有问题的,那么可以这样写:

if not FThread.Terminated thenbegin  FThread.Suspended := not FThread.Suspended;end;
或者:
if (not FThread.Terminated) and (FThread.Suspended) then    
  FThread.Resume;  

 

	
				
		
原创粉丝点击