Delphi多线程的OnTerminate属性(附加一个关于临界区线程同步的例子)
首先看TThread源码中关于OnTerminate的代码:
- public
- ....
- property OnTerminate: TNotifyEvent read FOnTerminate write FOnTerminate;
- ...
- end;
再看Delphi自带的帮助手册中对于OnTerminate的解释:
Occurs after the thread's Execute method has returned and before the thread is destroyed.
property OnTerminate: TNotifyEvent;
Description
Write an OnTerminate event handler to execute code after the thread finishes executing. The OnTerminate event handler is called in the context of the main thread, which means CLX methods and properties can be called freely.
翻译成中文的大致的解释就是:线程的该属性如果被赋值为一个方法,那么此方法将会在该线程的Execute方法执行完成并退出,但是线程还没有被释放之前执行。
但是这里只是讲到它的使用,而且还可能只是多种可以使用的地方之一,但是OnTerminate是什么,它的原理是什么并没有讲到,所以还需要再去钻研。
一个实际的例子:
- unit Unit1;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls;
- type
- TForm1 = class(TForm)
- btn1: TButton;
- procedure btn1Click(Sender: TObject);
- private
- procedure ThreadDone(Sender: TObject);
- public
- { Public declarations }
- end;
- TTestThread = class(TThread)
- protected
- procedure Execute; override;
- end;
- var
- Form1: TForm1;
- implementation
- {$R *.dfm}
- const
- MaxSize = 128;
- var
- NextNumber: Integer = 0;
- DoneFlags: Integer = 0;
- GlobalArray: array[1..MaxSize] of Integer;
- CS: TRTLCriticalSection;
- function GetNextNumber: Integer;
- begin
- Result:= NextNumber;
- Inc(NextNumber);
- end;
- procedure TTestThread.Execute;
- var
- i: Integer;
- begin
- OnTerminate:= Form1.ThreadDone; //在这里设置OnTerminate属性的值为Form1的ThreadDone方法,
- //表示在线程执行完Execute之后,还没有被释放之前,要紧接着执行Form1的ThreadDone方法。
- EnterCriticalSection(CS);
- for i:= 1 to MaxSize do
- begin
- GlobalArray[i]:= GetNextNumber;
- Sleep(5);
- end;
- LeaveCriticalSection(CS);
- end;
- procedure TForm1.ThreadDone(Sender: TObject);
- var
- i: Integer;
- begin
- inc(DoneFlags);
- if DoneFlags = 2 then
- begin
- for i:= 1 to MaxSize do
- lst1.Items.Add(IntToStr(GlobalArray[i]));
- DeleteCriticalSection(CS);
- end;
- end;
- procedure TForm1.btn1Click(Sender: TObject);
- begin
- initializeCriticalSection(CS);
- TTestThread.Create(False);
- TTestThread.Create(False);
- end;
- end.
先解释OnTerminate:在这里设置OnTerminate属性为Form1的ThreadDone方法,表示在线程执行完Execute之后,还没有被释放之前,要紧接着执行Form1的ThreadDone方法。
再对线程的同步进行说明:这里使用临界区进行线程的同步,该例程会在点击按钮之后开启两个线程。
每个线程都是对一个全局数组GlobalArray进行操作,使用了临界区的话,(看TForm1的btn1Click方法)虽然是连续开启两个线程,但是因为使用了临界区,而且是在线程的Execute中进行操作之前先进入临界区,所以当一个线程运行(也就是执行Execute方法)时,第一个线程进入临界区对全局数组GlobalArray进行性操作,那么另外一个线程就只能等待,等到第一个线程完成操作并且离开临界区之后(此时GlobalArray数组的值是从0到127)。第二个线程开始进入临界区,并且开始对GlobalArray进行操作,最后GlobalArray数组中的值是从128到255。
通过使用临界区就可以保证多个线程不能同时对一个资源进行操作,而如果没有使用临界区对线程进行同步的话,那么最后可能是线程1、线程2随机连续对数组进行操作(因为操作系统对线程的时间片的分配是随机的)(还有NextNumber这个全局变量也会被两个线程随机连续操作,可能造成冲突),最后的结果就是当两个线程都执行完成之后,GlobalArray数组中的值没有任何规律,所以这时候就不可能根据规则来控制线程,这时候开发出来的程序就是开发者所不能控制的,显然不利于程序的稳定性等。
所以在多个线程会去操作同一个资源等情况的时候,必须对线程进行同步,保证线程的可控性。
Delphi多线程的OnTerminate属性(附加一个关于临界区线程同步的例子)的更多相关文章
- java 多线程总结篇3之——生命周期和线程同步
一.生命周期 线程的生命周期全在一张图中,理解此图是基本: 线程状态图 一.新建和就绪状态 当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时它和其他的Java对象一样,仅仅由Jav ...
- Java基础-多线程-③线程同步之synchronized
使用线程同步解决多线程安全问题 上一篇 Java基础-多线程-②多线程的安全问题 中我们说到多线程可能引发的安全问题,原因在于多个线程共享了数据,且一个线程在操作(多为写操作)数据的过程中,另一个线程 ...
- 多线程,线程同步,synchronized关键字的用法
一.什么是多线程 Java多线程实现方式主要有四种:继承Thread类.实现Runnable接口.实现Callable接口通过FutureTask包装器来创建Thread线程.使用ExecutorSe ...
- java多线程(2) 线程同步
我们对线程访问同一份资源的多个线程之间,来进行协调的这个东西,就是线程同步. 例子1:模拟了多个线程操作同一份资源,可能带来的问题: package com.cy.thread; public c ...
- Java多线程之线程同步【synchronized、Lock、volatitle】
线程同步 线程同步:当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态,实现线程同步的方法有很多. ...
- Delphi多线程详解
(整理自网络) Delphi多线程处理 1-1多线程的基本概念 WIN 98/NT/2000/XP 是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用CPU 运行时间和资源,或者 ...
- 【转】Delphi多线程编程
文章来源: http://liukun966123.my.gsdn.net/2004/10/22/4797/ Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书 ...
- delphi 多线程3
多线程程序设计 我们知道,win95或winNT都是“多线程”的操作系统,在DELPHI .中,我们可以充分利用这一特性,编写出“多线程”的应用程序. 对以往在DOS或16位windows下写程序的 ...
- [转]Delphi多线程编程入门(二)——通过调用API实现多线程
以下是一篇很值得看的关于Delphi多线程编程的文章,内容很全面,建议收藏. 一.入门 ㈠. function CreateThread( lpThreadAttributes: Pointer ...
随机推荐
- Date类
Date类 构造方法: Date():根据当前的默认毫秒值创建对象 Date(long date):根据给定的默认毫秒值创建对象 成员方法: public long getTime():获取时间,以毫 ...
- oracle 序列中cache 有什么用途
create sequence name increment by x //x为增长间隔 start with x //x为初始值 maxvalue x //x为最大值 minvalue x //x为 ...
- .NET 的 WebSocket 开发包比较(转)
.NET 的 WebSocket 开发包比较 编者按 本文出现在第三方产品评论部分中.在这一部分的文章只提供给会员,不允许工具供应商用来以任何方式和形式来促销或宣传产品.请会员报告任何垃圾信息或广告. ...
- temp
netstat -tlnap lsof -i :40735 ps -ef|grep 10259 iftop iptraf nethogs gidxylxhqp http://blog.csdn.net ...
- Intellij Idea/Webstorm/Phpstorm 的高效快捷键
1. shift + F6可以理解为F2的豪华重量版,不但可以重命名文件名,而且可以命名函数名,函数名可以搜索引用的文件,还可以重命名局部变量.还可以重命名标签名.在sublime text中有个类似 ...
- Linux2.6.11版本:classic RCU的实现
转载自:http://www.wowotech.net/kernel_synchronization/linux2-6-11-RCU.html 一.前言 无论你愿意或者不愿意,linux kernel ...
- Altium Designer 的entry sheet ,offsheet和port作用(转载)
1.图纸结构 图纸包括两种结构关系: 一种是层次式图纸,该连接关系是纵向的,也就是某一层次的图纸只能和相邻的上级或下级有关系: 另一种是扁平式图纸,该连接关系是横向的,任何两张图纸之间都可以建立信号连 ...
- virut详细分析
Virut分析 0x00.综合描述 virut样本的执行过程大体可以分为六步:第一步,解密数据代码,并调用解密后的代码:第二步,通过互斥体判断系统环境,解密病毒代码并执行:第三步,创建内存映射文件,执 ...
- JavaScript的==和===运算符
JavaScript提供两个相等运算符:==和 ===. 简单说,它们的区别是相等运算符( ==)比较两个值是否相等,严格相等运算符( ===)比较它们是否为“同一个值”.如果两个值不是同一 ...
- angularjs向后台传递数据,与后端进行交互
angularjs之数据交互 function loadLeftFirstNodes (){ $http.get(sourceUrl,{ params:{ mpId: mpId, visits: ce ...