



版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第 10 章多线程应用程序Win32 操作系统提供了在应用Win32 的一个最大受益便是:它执行多线程的能力。从 16 位的 Windows 升级到多线程同时运行。这也是要升级到 32 位 Delphi 的一个最主要的。在很多情况下,需要采用多线程技术进行程序设计。例如,常用的微软拼音输入软件,当输入文字的时候,输入法同时在词库中进行搜索和检验,也就是将文档中的词语与词库中的词语进行比较,提供一些可能性给使用者。这些操作都比较耗费时间,但是我们在使用输入法的时候并没有感觉到输入过程有明显的滞后现象。这里输入法就采用了多线程技术,其中一个线程接收输入,另一个线程进行检验。本章主要对 Delphi
2、 环境中开发多线程应用程序进行探讨,并提供编程的一些细节。如何进行多线程10.1 进程与线程10.1.1进程和线程的概念在 DOS 操作系统中,用户一次只能运行一个程序。用户在计算机中启动一个程序后, 只有等它结束后才能运行另一个程序。这种类型的操作系统我们称为单任务的操作系统。而在Windows 操作系统中,用户一次可以启动多个程序,甚至还可以启动一个应用程序的多个实例。这样的操作系统我们称为多任务的操作系统。可以看出,静态的程序与在计算机中运行的程序是有明显区别的。为了清楚的表达这种观点,引入了进程的概念。进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其他各种系统组
3、成的。进运行过程中创建的随着进程的终止而被销毁,所使用的系统在进程终止时被或关闭。线程是进程内部的一个执行单元(如可以是一个函数或一个活跃的类对象等)。系统创建好进程后,实际上就启动执行了该进程的主执行线程。主执行线程终止了,进程也就随之终止。每一个进程至少有一个线程(即主执行线程,它无需由用户去主动创建,是应用程序启动后创建的),用户根据需要在应用创建其他线程,多个线程并发地运行在同一个进程中。一个进程中的所有线程都在该进程的虚拟地址空间中,使用这些虚拟地址空间、全局变量和系统,所以线程之间的通讯要比进程之间的通讯容易得多。多线程设计在实际中的使用较为广泛。使用多线程具有以下优点: 由于 C
4、PU 的处理速度比较快,可以使用户在做一件事情的时候还可以做另外一件事。 在多个 CPU 的情况下,可以充分利用硬件的优势:将一个大任务分成几个小任务由不同的 CPU 来完成。292 第 10 章 多线程应用程序 可以为每个线程设置优先级,调整工作的进度。多线帮助解决某些问题的同时,也有一些问题,如线程间切换时,消耗大量CPU时间,延长整个工作的时间;多个线程对数据进行读写时,数据的安全性可能会受到破坏等。所以,进行多线程的程序设计,要充分考虑到设计的可行性和安全性,发挥出并行运行的高效性,最大限度地提高程序的效率。10.1.2线程调度多任务操作系统要完成多个任务的并行运行,需要管理和调度不同
5、的线程来使用微处理器的运行时间。根据线程调度方式的不同,分为抢先式调度和非抢先式调度。1非抢先式调度在非抢先式操作系统中,一个线程只有完成线程调度程序所指定的时间片后,处理器的权交还给该程序调度程序,程运行期间,其他线程只有等待其将处理器的权交还。Windows3.1 就是一个非抢先式操作系统。采用非抢先式调度的操作系统实时性比较差。2抢先式调度抢先式操作系统采用以下调度策略: 当线程运行完调度程序所分配的时间片后,将处理器的调度程序重新进行调度分配。权交还给调度程序,有程运行时间片完成之前,在下列场合下,操作系统的线程调度程序可以终止线程的运行,重新进行线程调度。如:正在运行的线程调用 Sl
6、eep 方法;更高优先级的线程希望获得处理器;线程处于阻塞状态。采用抢先式调度的操作系统适用于实时性较强的系统,它对高优先级的任务具有较好的响应性。Windows98 和Windows NT 操作系统都是抢先式操作系统。10.2TThread 对象Delphi 把有关线程的 API 封装在 TThread 这个 Object Pascal 的对象中。虽然 TThread 已经封装了几乎所有与线程有关的 API。但在某些情况下,尤其在处理线程同步的问题时,仍需调用一些别的 API 函数。本节将介绍 TThread 用法。10.2.1Tthread 类的属性1Suspended 属性属类型。TTh
7、read 构件的 Suspended 属性用于确定线程是否处于暂停状态。2Terminated 属性属类型。在应用程序运行过程中,如果设置 Terminated 属性参数为 True,则表明应用程序希望线程尽快结束运行程构件的方法 Excute 中,应该检查线程对象的 Terminated第 10 章 多线程应用程序 293属性参数,如果该属性参数被置为 True,则线程对象应该立刻终止运行。VCL 主线线程可以通过调用线程对象的 Terminate 方法来设置 Terminated 属性参数为 True。其他3Priority 属性属 TThreadPriority 类型。Priority
8、属性用于设置线程对象的相对优先级。线程的优先级是相对同一个进程中的其他线程而言的。4FreeOnTerminate 属性属类型。FreeOnTerminate 属性用于确定当线程终止时是否自动删除线程对象。缺省情况下该属性参数为 True。5ReturnValue 属性整数类型。当线程终止时,通过 ReturnValue 属性参数向其他线程传递一个值。6ThreadID 属性线程标识号属性。是整个系统中线程的标识号。使用 Windows API 函数的时候该属性非常有用。10.2.2TThread 类的方法1Execute 方法Execute 方法是一个虚函数,需要在 TThread 类中给出
9、定义。方法原型如下所示:procedure Execute ; virtual ; abstract ;Delphi 多线程中 VCL 主线程完成应用程序的主要功能,如消息循环,、主窗口的,而其他的多个线程仅仅完成辅助的功能。在设计和实现一个线程类时,需要在 Execute 过程中给出线程需要完成的任务代码。2Resume 方法当线程对象处于暂停状态时,调用此方法使线程恢复运行。方法原型如下所示:procedure Resume ;3Suspend 方法当线程对象运行时,调用此方法使线程对象暂停运行。方法原型如下所示:procedure Suspend ;4Terminate 方法当线程对象运
10、行时,其他线程对象通过 Terminate 方法设置线程对象的 Terminate 属性为True,通知线程终止运行。方法原型如下所示:procedure Terminate ;294 第 10 章 多线程应用程序5DoTerminate 方法调用对象的 DoTerminate 方法,使线程对象产生 OnTerminate。方法原型如下所示:procedure DoTerminate ; virtual ;6Synchronize 方法VCL 主线窗口及其所包含的构件对象实施管理。而在其他线程中,如果随意主窗口或它所包含的构件对象,则有可能发生多个线程同时一个的情况,使应用程管理的或构件对象,
11、需要通过 Synchronize 方法序。为了在工作线程中主线进行。当工作线程使用 Synchronize 方法VCL 主线管理的构件对象时,工作线不构件和操作,而是要等到 VCL 主线和操作,这样就避免了两个线程产生立即进行对象进行应用程序消息队列获取消息时,。该方法原型如下所示:procedure Synchronize(Method: TThreadMethod) ;7WaitFor 方法等待线程对象终止,并且返回线程对象的 ReturnValue。该方法原型如下所示:function WaitFor : LongWord ;10.2.3TThread 类的程对象的 Execute 方法
12、返回后并于通知应用程序,此线程即将结束。程对象被删除前,产生 OnTerminate,用10.2.4 创建线程类利用 TThread 类来编写多线程应用程序的一般步骤如下:(1) 从 TThread 类派生出一个新的线程类。(2) 创建线程对象。(3) 设置线程对象的属性,比如优先级等。(4) 根据具体情况挂起或唤醒线程。(5) 结束线程。下面我们来看一个从 TThread 类派生出新的线程类的实例。激活菜单“File/New”打开 New Items框,选中 New中的 Thread Object 项,点击 OK 按钮。在接着弹出的 New Thread Object框中输入新的线程类的名称
13、。通常线程类的名称以 T 开头,以 Thread 结束。在 New Thread Object框框中输入完毕后点击 OK按钮,Delphi 会自动生成一个 TThread 类的派生类,并将代码保存在一个新的单独的文件中。例如:unit Unit3;interfaceuses第 10 章 多线程应用程序 295Classes;typeTTestThread = class(TThread) private Private declarations protectedprocedure Execute; override;end;implementation Important: Methods
14、and properties of objects in VCL can only be used in a method called using Synchronize, for example,Synchronize(UpdateCaption);and UpdateCaption could look like,procedure TTestThread.UpdateCaption; beginForm1.Caption := Updated in a thread; end; TTestThreadprocedure TTestThread.Execute; begin Place
15、thread code here end;end.10.2.5线程的初始化操作集成开发环境仅产生了线程类的框架,用户应该根据应用程序的要求,进行以下两个方面的初始化工作设置线程的优先级和设置线程的清除标志。程初始化时,编程要根据线程任务的特点,给线程设置相应的线程优先级。还要指出,线方式。运行结束时,如何线程对象。根据线程使用情况的不同,可以采用不同 一般情况下,一个线程对象仅需运行一次。这种情况下,线程运行结束时,由线程对象自身线占用的。 在有些场合,如一个线程对象需要启动多次来完成应用程序的任务时,当线程对象执行任务完毕后,不能删除此线程对象。设置 FreeOnTerminate 属性参数
16、为 False。10.2.6实现线程对象的功能程类的 Execute 方法中,编程需要给出线程对象的功能代码。procedure TTestThread.Execute;begin296 第 10 章 多线程应用程序Synchronize(UpdateCaption);end;procedure TTestThread. UpdateCaption; beginForm1.Caption := Updated in a thread;end;10.3线程的同步在多线程应用,进程中的多个线程共同存在于进程的虚拟地址空间中,它们共享进程的所有。因此如果发生多个线程同时或操作进程的某一个时,将会使应
17、用程序产生意想不到的错误。所以在程序设计时,要考虑多个线程如何同步的使用进程的共享,以避免线程间产生。由于 Delphi 不支持多线程同时可视对象库(VCL),所以在编写多线程程序VCL 的时候要特别注意,只能逐个地实现对 VCL 的。具体可以采用下面的两个方法:(1)对于一些具有锁定功能的对象,可以在锁定之后再进行具体操作例如 TCanvas 类有一个 Lock 过程,可以行过程中,在调用画布作图之前,调用 Lock 过过程解除锁定。其他线画布上作图。所以程的执画布锁定。作图过程完成之后,调用 Unlock需要注意的一点:TCanvas 还有一个只读属性 LockCount。在调用 Lock
18、 过程的时候, LockCount 将逐渐增加;当调用 Unlock 过程的时候,LockCount 将逐渐减少。当 LockCount 为零时,其他线程才可以在画布上作图。此外,TCustomWinSocket、TGraphicsObject 和 TRemoteDataModule 等类也具有 Lock 和UnLock 过程。(2)使用 Synchronize 函数TThread 类的 Synchronize 过程原型如下:type TThreadMethod = procedure of object;procedure Synchronize(Method: TThreadMethod)
19、;其中参数 Method 为一个不带参数的过程名。在这个不带参数的过程中是一些的代码。VCL可以在 Execute 过程中调用 Synchronize 过程来避免对 VCL 的并发。程序运行期间的具体过程是由 Synchronize 过程来通知主线程,然后主线适当的时机执行 Synchronize过程的参数列表中不带参数的过程。在多个线程的情况下,主线Synchronize 过发的通知放到消息队列中,然后逐个地响应这些消息。通过这种机制 Synchronize 实现了线程之间的同步。第 10 章 多线程应用程序 297图 10-1 多线程应用演示程序所以,可以将对 VCL的代码写在一个不带参数
20、的过程中,然后将过程名作为Synchronize 过程的参数在 Execute 过程中进行调用。例如:procedure TMyThread.PushTheButton; beginButton1.Click();end;procedure TMyThread.Execute; begin. . .Synchronize(PushTheButton);. . .end;下面我们来看一个多线程应用程序的例子,程序包含了三个线程一个 VCL 主线程和两个工作线程(文件线程和数据分析线程)。主窗体如图 10-1 所示。参考图 10-1 在窗体中添加组件,根据需要设置相应属性。程序代码如下:/unit
21、 Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls,/应用程序窗体构件定义types,syncobjs,unit2,unit3;298第 10 章 多线程应用程序TForm1 = class(TForm)Main File1: T Start1: TExit1: T1: TMain Item; Item;Item;Memo1: TMemo;procedure Start1Click(Sender: TObject); pro
22、cedure Exit1Click(Sender: TObject); procedure FormCreate(Sender: TObject);procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure FormDestroy(Sender: TObject);private public Private declarations ReadFileOkEvent:TEvent;AnalyzeOkEvent:TEvent;/读文件/数据分析对象对象线程对象ReadFileThread:TReadFil
23、eThread; /文件AnalyzeThread:TAnalyzeThread; public Public declarations end;/数据分析线程对象varForm1: TForm1;implementation$R *.dfmprocedure TForm1.Start1Click(Sender: TObject); beginReadFileThread.Resume; AnalyzeThread.Resume;end;procedure TForm1.Exit1Click(Sender: TObject); beginClose;end;procedure TForm1.F
24、ormCreate(Sender: TObject); beginReadFileOkEvent:=TEvent.Create(nil,true,false,ReadThread);/创建ReadFileOkEvent对象ReadFileOkEvent.ResetEvent; /设置ReadFileOkEvent对象为无信号状态AnalyzeOkEvent:=TEvent.Create(nil,true,true,AnalyzeThread);第 10 章 多线程应用程序 299/创建AnalyzeOkEvent对象AnalyzeOkEvent.SetEvent;/设置AnalyzeOkEve
25、nt对象为有信号状态ReadFileThread:=TReadFileThread.Create(true);/创建ReadFileThread线程对象ReadFileThread.FreeOnTerminate:=false;/设置线程FreeOnTerminate标志AnalyzeThread:=TAnalyzeThread.Create(true);/创建AnalyzeThread线程对象AnalyzeThread.FreeOnTerminate:=false;/设置线程FreeOnTerminate标志end;procedure TForm1.FormCloseQuery(Sender
26、: TObject; var CanClose: Boolean); beginReadFileThread.Terminate; AnalyzeThread.Terminate;end;procedure TForm1.FormDestroy(Sender: TObject); beginReadFileOkEvent.Free; AnalyzeOkEvent.Free; ReadFileThread.Free; AnalyzeThread.Free; Memo1.clear;end;end./unit Unit2;interfaceusesClasses;typeTReadFileThre
27、ad = class(TThread) privateprocedure Update; Private declarations protectedprocedure Execute; override;end;implementationuses Unit1;300第 10 章 多线程应用程序 Important: Methods and properties of objects in VCL or CLX can only be usedin a method called using Synchronize, for example,Synchronize(UpdateCaption
28、);and UpdateCaption could look like,procedure TReadFileThread.UpdateCaption; beginForm1.Caption := Updated in a thread;end; TReadFileThread procedure TReadFileThread.Update; beginForm1.Memo1.Lines.Append(ReadFile Thread:Now Reading);end;procedure TReadFileThread.Execute; begin Place thread code here
29、 while(Form1.AnalyzeOkEvent.WaitFor(100)=wrSignaled)do beginif(Terminated)then exit;/检查线程的标志,如果为true,则线程停止Form1.AnalyzeOkEvent.ResetEvent;/AnalyzeOkEven Synchronize(Update);/模拟文件Form1.ReadFileOkEvent.SetEvent();/ReadFileOkEvenend; end;设置为无信号状态过程设置为有信号状态end./unit Unit3;interfaceusesClasses;typeTAnaly
30、zeThread = class(TThread) private Private declarations procedure Update;protected第 10 章 多线程应用程序 301procedure Execute; override;end;implementation uses Unit1; Important: Methods and properties of objects in VCL or CLX can only be usedin a method called using Synchronize, for example,Synchronize(Updat
31、eCaption);and UpdateCaption could look like,procedure TAnalyzeThread.UpdateCaption; beginForm1.Caption := Updated in a thread;end; TAnalyzeThread procedure TAnalyzeThread.Update; beginForm1.Memo1.Lines.Append(Analyze and Display Thread:Now Analyze and Display);end;procedure TAnalyzeThread.Execute; b
32、egin Place thread code here while(Form1.ReadFileOkEvent.WaitFor(100)=wrSignaled)do beginif(Terminated)then exit;/检查线程的标志,如果为true,则线程停止Form1.AnalyzeOkEvent.ResetEvent;/ReadFileOkEven设置为无信号状态Synchronize(Update);/模拟文件数据分析过程Form1.AnalyzeOkEvent.SetEvent();/AnalyzeOkEven设置为有信号状态end;end;end.程序在进程内设置两个对象,分别表明文件操作和数据分析操作是否完毕。当文件进程部分文件数据后,通过一个对象通知数据分析和显示线程,对的数据进行分析和显示。当数据分析和现实线程处理完成它所读入的数据,则利用另外一个事件对象通知文件线程,继续文件数据。请读者参照注释读懂这
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 浙江国企招聘2025台州湾新区招聘7人笔试参考题库附带答案详解
- 浙江国企招聘2024浙江省文化产业投资集团有限公司招聘14人笔试参考题库附带答案详解
- 二零二五年度企业入驻高新技术产业园区入驻合同
- 二零二五年度工程款抵扣工程结算审计协议
- 二零二五年度地下停车场车位出售合同协议
- 二零二五年度事业单位解聘合同模板(绿化养护人员岗位)
- 2025年度深圳租房合同租赁期限变更与租赁物维护服务协议
- 二零二五年度电商直播平台主播劳动合同
- 2025年度新能源储能技术股东合作协议书
- 二零二五年度新能源电池回收利用合作开发协议范本
- 老旧小区基础设施环境改造工程施工质量因素的分析及控制方法
- 伊斯兰教完整版本
- 华师版初中九年级数学HS下册教案(全一册)
- 2024年10月自考00107现代管理学试题及答案
- 2024解析:第十八章电功率-讲核心(解析版)
- 2024年新疆区公务员录用考试《行测》真题及答案解析
- 严重创伤患者紧急救治血液保障模式与输血策略中国专家共识(2024版)
- 【川教版】《生命 生态 安全》五下全册课件
- 英文在职证明模版
- 中国无人机市场分析
- 2025高考数学专项复习:圆中鬼魅阿波罗尼斯圆(含答案)
评论
0/150
提交评论