打印本文 打印本文 关闭窗口 关闭窗口
Delphi线程类的使用(1)
作者:武汉SEO闵涛  文章来源:敏韬网  点击数2309  更新时间:2009/4/23 18:29:27  文章录入:mintao  责任编辑:mintao

Execute方法

通过Synchronize发送消息给主线程并等待

SyncProc方法

一段受Synchronize保护的代码

WM_NULL消息处理

创建线程

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


再来看类的实例化细节。线程类的实例化与一般类大体相同,但也有其不同之处,最大的不同就是,它在进行实例化的同时还创建了一个线程(即ThreadProc的执行)。

对于一般类的实例化来说:首先是调用类构造器(Constructor)Create,而Create的工作首先就是在进程的堆空间中分配类的数据区(包括类的数据成员和一些必要额外数据),然后把这个数据区的指针作为Self参数调用Create完成构造工作。此后,我们所用到的类实例,其实具体的就是这个数据区。比如我们要调用某个类实例(SomeObject)的某成员方法(SomeMemberMethod)如下:

SomeObject.SomeMemberMethod(Parameters);

其实就等效于:

TSomeClass.SomeMemberMethod(SomeObject, Parameters);

其中TSomeClass就是类实例SomeObject对应的类,而相应的,类实例SomeObject被作为隐含参数Self传递到方法内部。

而在方法内部访问类数据成员(SomeMemberData)时:

Function TSomeClass.SomeMemberMethod(Parameters) : SomeType; // 因为实际上Self是隐含传递的

Begin

     Result := SomeMemberData;

End;

其实等效于Self.SomeMemberData。

对于线程类的情况,与上面说的基本相同。

但是有一个最大的不同就在于:线程类实例会创建自己独立的栈(由线程函数ThreadProc隐含创建),而普通类是使用主线程栈的。这就是意味着,在子线程中使用局部变量是安全的,因为局部变量是分配在栈中的。各个线程都有自己的栈(包括主线程),而且一般情况下是无法直接访问别的线程的栈空间的,除非是一些极端的情况(如将局部变量通过指针传给其它线程供操作),局部变量都不需要访问冲突保护。

但这不表示线程类数据成员(如前面的FData)安全,因为它们是分配在进程的堆空间中。当然,每个线程类对象都有各自独立的数据成员,正常情况下只要不互相访问,它们仍然是安全的。但是如果需要让别的线程,特别是主线程使用线程类数据成员,就一定要考虑到访问冲突保护的问题(如前面的例子,FData通过Foo函数导致了主线程对它的访问),因为这种冲突访问通常是通过线程类本身的方法/属性间接进行的,有时很容易被忽视。

实现后的线程类运行时情况如下图:

 

主窗体代码

线程类代码

SomeMemberMethod

主线程栈

堆空间

线程类实例1数据:SomeMemberData

线程类实例2数据:SomeMemberData

线程1的栈

线程2的栈

代码区  数据区

 

 

 

 

 

 

 

 

 

 

上一页  [1] [2] [3]  下一页

打印本文 打印本文 关闭窗口 关闭窗口