Delphi中的线程类--之(3)

类别:Delphi 点击:0 评论:0 推荐:

Delphi中的线程类

 

猛禽[Mental Studio]

http://mental.mentsu.com

 

之三

说完构造函数,再来看析构函数:

destructor TThread.Destroy;

begin

  if (FThreadID <> 0) and not FFinished then

  begin

    Terminate;

    if FCreateSuspended then

      Resume;

    WaitFor;

  end;

  if FHandle <> 0 then CloseHandle(FHandle);

  inherited Destroy;

  FFatalException.Free;

  RemoveThread;

end;

在线程对象被释放前,首先要检查线程是否还在执行中,如果线程还在执行中(线程ID不为0,并且线程结束标志未设置),则调用Terminate过程结束线程。Terminate过程只是简单地设置线程类的Terminated标志,如下面的代码:

procedure TThread.Terminate;

begin

  FTerminated := True;

end;

所以线程仍然必须继续执行到正常结束后才行,而不是立即终止线程,这一点要注意。

在这里说一点题外话:很多人都问过我,如何才能“立即”终止线程(当然是指用TThread创建的线程)。结果当然是不行!终止线程的唯一办法就是让Execute方法执行完毕,所以一般来说,要让你的线程能够尽快终止,必须在Execute方法中在较短的时间内不断地检查Terminated标志,以便能及时地退出。这是设计线程代码的一个很重要的原则!

当然如果你一定要能“立即”退出线程,那么TThread类不是一个好的选择,因为如果用API强制终止线程的话,最终会导致TThread线程对象不能被正确释放,在对象析构时出现Access Violation。这种情况你只能用API或RTL函数来创建线程。

如果线程处于启动挂起状态,则将线程转入运行状态,然后调用WaitFor进行等待,其功能就是等待到线程结束后才继续向下执行。关于WaitFor的实现,将放到后面说明。

线程结束后,关闭线程Handle(正常线程创建的情况下Handle都是存在的),释放操作系统创建的线程对象。

然后调用TObject.Destroy释放本对象,并释放已经捕获的异常对象,最后调用RemoveThread减小进程的线程数。

 

其它关于Suspend/Resume及线程优先级设置等方面,不是本文的重点,不再赘述。下面要讨论的是本文的另两个重点:Synchronize和WaitFor。

 

但是在介绍这两个函数之前,需要先介绍另外两个线程同步技术:事件和临界区。

 

事件(Event)与Delphi中的事件有所不同。从本质上说,Event其实相当于一个全局的布尔变量。它有两个赋值操作:Set和Reset,相当于把它设置为True或False。而检查它的值是通过WaitFor操作进行。对应在Windows平台上,是三个API函数:SetEvent、ResetEvent、WaitForSingleObject(实现WaitFor功能的API还有几个,这是最简单的一个)。

这三个都是原语,所以Event可以实现一般布尔变量不能实现的在多线程中的应用。Set和Reset的功能前面已经说过了,现在来说一下WaitFor的功能:

WaitFor的功能是检查Event的状态是否是Set状态(相当于True),如果是则立即返回,如果不是,则等待它变为Set状态,在等待期间,调用WaitFor的线程处于挂起状态。另外WaitFor有一个参数用于超时设置,如果此参数为0,则不等待,立即返回Event的状态,如果是INFINITE则无限等待,直到Set状态发生,若是一个有限的数值,则等待相应的毫秒数后返回Event的状态。

当Event从Reset状态向Set状态转换时,唤醒其它由于WaitFor这个Event而挂起的线程,这就是它为什么叫Event的原因。所谓“事件”就是指“状态的转换”。通过Event可以在线程间传递这种“状态转换”信息。

当然用一个受保护(见下面的临界区介绍)的布尔变量也能实现类似的功能,只要用一个循环检查此布尔值的代码来代替WaitFor即可。从功能上说完全没有问题,但实际使用中就会发现,这样的等待会占用大量的CPU资源,降低系统性能,影响到别的线程的执行速度,所以是不经济的,有的时候甚至可能会有问题。所以不建议这样用。

(待续)

本文地址:http://com.8s8s.com/it/it5213.htm