说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

使用Delphi 4.0编写多线程

HTML文档下载 WORD文档下载 PDF文档下载
使用Delphi 4.0编写多线程

1.介绍

VCL提供几个对象以方便编写多线程应用。使用多线程可以避开一些性能的瓶颈。使用不同优先权的线程可以给重要的任务更多的CPU时间。在多处理器机器上,使用多个线程并将不同的线程放在不同的处理器上运行,将会提高应用的性能。当有相应的底层硬件时,NT操作系统支持真正的多线程,而即使底层硬件支持多处理器,95也只能模拟多线程的运行。

2.定义线程对象

对于大多数应用,可以使用线程对象来表示一个执行的线程。线程对象封装线程必需的应用,简化了多线程的编写。

注意:多线程对象并不允许泥控制线程的安全属性或栈的大小。如果需要控制这些,必须使用BeginThread函数。即使使用BeginThread,仍然能从一些线程同步的对象和在定位相差的方法中获取好处。

为了在应用中使用线程对象,首先必须产生一个TThread的继承对象。在file|new菜单中选择Thread Object创建。

新产生的Thread Object 包括一个框架代码,以下是一个名为TMyThread的线程:

unit Unit2;

interface

uses

Classes;

type

TMyThread = class(TThread)

private

{ Private declarations }

protected

procedure Execute; override;

end;

implementation

{ TMyThread }

procedure TMyThread.Execute;

begin

{ Place thread code here }

end;

end.

在自动产生的unit文件中,你应该:

l (可选)初始化线程

l 填写Execute方法,编写线程函数

l (可选)编写清除代码

3.初始化线程

如果你要为线程编写初始化代码,必须重载Create方法。在线程的声明中加入一个新的构造函数,并在它的实现中编写初始化代码。在这里你能够为线程设置一个缺省的优先级和当它执行完毕时,是否应该自动的释放。

3.1 设置一个缺省的优先级

优先级分为7级,如下表所示:

TpIdle The thread executes only when the system is idle. Windows won't

interrupt other threads to execute a thread with tpIdle priority.

TpLowest The thread's priority is two points below normal.

TpLower The thread's priority is one point below normal.

TpNormal The thread has normal priority.

TpHigher The thread's priority is one point above normal.

TpHighest The thread's priority is two points above normal.

TpTimeCritical The thread gets highest priority.

警告:一味地提高对CPU敏感的操作的线程的优先级会饿死其它线程。应该提高那些经常等待外部事件的线程的优先级。以下的代码表示一个低优先级的执行后台任务的线程,它在其它的时间内不会打扰应用的执行。

constructor TMyThread.Create(CreateSuspended: Boolean);

{

inheritedCreate(CreateSuspended);

Priority := tpIdle;

}

3.2 指明线程的释放

一般情况下,线程只会被执行一次,在这种情况下,特别方便让线程释放它自身,只要简单的将FreeOnTerminate特性置为true。如果需要多次运行,或同一个线程的多个实例,你可以缓存线程以提高性能,这时,将FreeOnTerminate特性置为false。

4.编写Execute方法

Execute方法是线程的函数。泥可以将它想象成一个由你的应用启动的程序,只是它共享了同样的进程空间。写线程函数稍微要注意一点是要确信没有写其他进程使用的内存,另外,你优可以使用共享内存在不同的线程之间通信,因为它们是在同一个进程空间中。

4.1 使用主VCL线程

当你使用从VCL继承过来的对象,他们的特性和方法并不能保证是线程安全的,即,访问特性货方法也许会执行一些使用一些没有被其他线程保护的内存。因此,为VCL对象的访问设了一个主VCL线程。这是处理应用程序中组件接收的所有的Windows消息的线程。 如果所有对象是在同一个线程中访问特性和方法,就不必担心会发生冲突。为了使用主VCL线程,产生一个分离的过程来执行需求的操作,在你的线程中使用Synchronize方法来调用这个分离的过程。如:

procedureTMyThread.PushTheButton;

begin

Button1.Click;

end;

procedure TMyThread.Execute;

begin

....

Synchronize(PushTheButton);

....

end;

Synchronize等待主VCL线程进入消息循环,然后执行相应的方法数据访问组件和图形组件都是线程安全的,不需要使用主VCL线程。

4.2 Thread-local变量

Thread-local变量是一种线程内的全局的变量,但是并不与其他的线程实例共享。声明thread-local变量是在threadvar区中声明,如:

threadvar

x : integer;

threadvar区只适用于全局变量。

5. 编写清除代码(Clean-up Code)

线程结束时执行的清除代码可以集中起来。当线程关闭前,一个OnTerminate事件发生。将清除代码都放在OnTerminate事件的处理代码中,这样,这些代码就总会被执行。

OnTerminate事件处理并不是作为线程的一部分运行,它是在主VCL线程环境(Context)下运行。有两个含义:在OnTerminate事件处理中不能使用任何线程局部变量可以安全的访问任何组件和VCL对象,而不必担心会与其它的线程冲突

6.避免同时访问

为了避免与其他线程在访问一个全局对象货变量时发生冲突,需要在执行线程代码时锁定其他线程的执行,直至完成操作。VCL支持三种技术来达到这个目的:

(1) 锁定对象:有些对象自己有锁定的功能,如canvas

(2) 使用critical区

如果对象没有提高内置的锁定功能,需要使用critical区,Critical区在同一个时间只也许一个线程进入。为了使用Critical区,产生一个TCriticalSection全局的实例。TcriticalSection有两个方法,Acquire(阻止其他线程执行该区域)和Release(取消阻止)

每个Critical区是与你想要保护的全局内存相关联。每个访问全局内存的线程必须首先使用Acquire来保证没有其他线程使用它。完成以后,线程调用Release方法,让其他线程也可以通过调用Acquire来使用这块全局内存。

警告:Critical区只有在所有的线程都使用它来访问全局内存,如果有线程直接调用内存,而不通过Acquire,会造成同时访问的问题。例如:LockXY是一个全局的Critical区变量。任何一个访问全局X

Y的变量的线程,在访问前,都必须使用Acquire

LockXY.Acquire; { lock out other threads }

try

Y := sin(X);

finally

LockXY.Release;

end;

(3) 使用multi-read exclusive-write synchronizer

当你使用critical区保护全局内存时,同一个时间内只允许一个线程使用这块内存。这也许会超过你的要求,特别是对于那些经常读而很少写的对象或变量。在多线程内,当没有线程对同样的内存进行写操作时,同时读它是没有任何问题。当你有一些全局变量需要经常读而很少写时,可以使用TmultiReadExclusiveWriteSynchronizer保护它们。这个对象象Critical section

但是当内存没有线程在写它时,允许多个线程读取一个内存。

为了使用multi-read exclusive-write synchronizer,产生一个全局的 TmultiReadExclusiveWriteSynchronizer实例,与你想要保护的内存相关联。每个线程如果项读取该内存,必须先调用BeginRead方法。它确信没有其他的线程在写内存。读完后,调用EndRead。写内存时,调用BeginWrite,写完后,调用 EndWrite。

警告:同Critical section一样,multi-read exclusive-write synchronizer也只有在所有的线程都使用它访问同一块全局内存时才有效。直接访问该内存将会导致同时访问问题。

7.线程对象的执行

使用线程时,首先产生一个线程的实例,可以立刻开始运行线程,也可以开始把它置于挂起(Suspended)状态,以后使用Resume方法运行它。将构造函数中的CreateSuspended参数置为false,线程将创建后立刻运行,如:SecondProcess := TMyThread.Create(false); {create and run the thread }一般在单处理器的机器上,一个进程适合产生16个线程,如果线程都在运行,那么线程的数目要更少一些。

暂停线程:调用suspend

恢复线程:调用resume

终止线程:调用Terminate,它将线程的Terminated特性置为true。如果Execute编写合理,它将周期性检查Terminated,当Terminated为True时,将终止线程的执行。如:

procedure TMyThread.Execute;

begin

while not Terminated do

PerformSomeTask;

end;

缓存线程

当应用需要同一个线程的多个实例(多次运行一个线程),可以缓存线程,以后重用,以提高性能,而不是每次创建一个新的线程。为了缓存线程,使用一个线程列表来维护线程。

电话拨号 -VB资料 电子邮件的标准格式 (RFC 822)-VB资料 断开拨号网络的连接-VB资料 断开与 Internet 的连接 -VB资料 发送电子邮件附件-VB资料 VB获得用户网络登录名 基 于Win95 的VB5 串 口 通 信 程 序 基于Win95的VB5串口通信程序 检测运程数据传送的断线-VB资料 简单电子邮件发送程序-VB资料 VB建立拨号联接 -VB资料 将所有窗口最小化-VB资料 VB利用IE控件访问Internet VB利用IE控件设计简易浏览器 VB利用Mscomm32控件判断MODEM是否打开,或者正在工作,并且判断拨号时是否遇忙音 VB利用TAPI进行电话拨号 利用VB访问Internet 利用VB设计聊天室 利用Visual Basic实现无线通讯 VB利用Winsock控件实现局域网通信 VB如何从 Internet 上取回某一个网页的內容? VB如何检测是否已连接到Internet? VB如何利用Winsock控件编写自己的Internet程序 VB如何每天抓取 Internet 上某一个网页中的图片来更换桌面的壁纸 VB如何启动拨号网路中的连线? VB如何使用MSCOMM32.OCX发送大于80H的字符,可否给个示例程序? VB如何用VB打开默认浏览器或默认发信程序? VB如何用Visual Basic编写小型的网络系统 VB如何在程序中启动 NT 的【拨号连接】对话框? VB如何在网页上使用 VB5 制作的 ActiveX 控件? VB如何中断【拨号网络连接】? 急件:怎样动态加载或引用DLL文件 我的SERVLET为何不能响应? 在两个表连接查询时为什么总报错:“Table is read only”? *************小问题,在线等待************** 关于更改程序名字的问题! 关于计算机远程终端控制问题 关于onload ASP的参考手册是什么? 更新数据库的日期时间问题!!! 为什么用insert 语句插入数据,数据长度只有4k左右? exchange 出现的怪问题 入门 菜问题 连接服务器的问题 我这是怎么了? 非常着急,关于bean的问题 在单元格中插入html? 关于两个大表连接和索引的问题 灌水、抢分 echo命令的具体使用方法? 在BIOS密码之后,系统引导之前加密计算机的软件有哪些?请帮忙呀 请问 如何获得mysql的原码 关于onload VB中如何使用资源文件?急!急!急! 关于思路,高分求教!分数不够在添 不得不提问了: 怎样防止用户重复登陆!???? **请问Kylix3在红帽7上如何安装? TEST 求php的win98下开发环境,大家帮帮忙。 我想做一个类似于邮件系统中附件功能的程序,请问用的是什么协议,那里有源码? 为什么输出结果不正确呢??? 急救!用ADO在98下与2K下不能同时运行! 主板的认识! 如何删除相同的两条记录 有关Blob造型成oracle.sql.BLOB的问题。 急死我了!!!RS485通讯的奇怪问题,请高手帮忙! 怎样在delete记录时不往log文件中写东西? 签名支持JK10000行动,同意签名者,进来跟贴!到时候咱们的真名或ID会被复印在传单背面,抵制日货,保卫钓鱼岛!!!!!!!!!!!! 迷惑!!!!!高手指点,值得讨论,谢谢! char型怎么转换成String型?(答对结帖) 请问 哪位大侠有loadrunner的中文测试资料提供一下,非常感谢! JS和ASP的问题????? 高手指点 这样划分vlan可不可以???? 数据库超时 VB+SQl 2000 如何实现在程序运行时加减代码? 各位高手给我个提示有关手动添加消息映射的 关于EjbOBJECT和EJBLOCALOBJECT在使用上的区别?? 寻找中俄文转换的工具软件!急! 请问怎么把CLASS程序打包成JAR程序? 如何在VC中嵌入对Access表tableApp中纪录个数的统计(在线等)? 学习java到底有没有前途?? 温岭坞根岭隧道今起封闭施工衢州两历史文化街区房屋收购开始签约湖州干部选拔任用采取空岗预告和网上推湖州撤地建市30周年 已经向工业强市温州市民卡服务项目公示一年未开通 随钱塘江上开轮渡初步设定4条航线杭州地铁2号线东南段全线洞通 计划明7月1日开始杭州火车南站将停办客运业杭州地铁1号线火车东站站月底迎客杭州治堵车辆道路违停 或将直接被拖离昨天杭州最高气温36.4℃为62年来嘉绍大桥月底通车 绍兴到上海缩短至1金华市区拟取消900个路面停车位金华拟提拔6位结构性市管干部 最年轻杭州火车东站开通在即 火车南站将暂别杭州地铁18天三次因故障停车 民众质厦深高铁或年底前开通 温州到深圳6个浙江再掀撤县设区热:洞头撤县设区方案杭州不少小区游泳池成本太高成鸡肋杭州主城区年底前取消1000只屋顶水杭城1356个红绿灯近半能自动调时间在镇街办事可享证照文书包邮时报体育频道新一代运载火箭长征五号昨晚首飞成功 探访增城小楼镇报德祠 广州唯一一座三丁俊晖解释失控原因:精神绷紧导致情绪国足首练,“严防”媒体4战151分,场均三双 愤怒的威斯布龙口西又多了一个河边花园一孩二孩半岁前要办理生育登记橘子皮泡脚可除菌润肤首个国家森林城市群建设规划即将出炉弘扬伟大长征精神 走好新的长征路 推丈夫有婚外情,离婚可要求精神损害赔偿出招防作弊 印度公务员考试 禁止文交通部门:小心的士“叠表”猫腻中学生学习压力大?高空抛杂物两个钟南昌检方证实副科长拥149套房 购买夜宵噪音令孕妇难眠警方联合城管解民忧作业太多 西班牙家长力挺孩子“罢写”提前投票 希拉里有优势特朗普号召“悔黄埔将建中大肿瘤中心新院区
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘