首先看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属性(附加一个关于临界区线程同步的例子)的更多相关文章

  1. java 多线程总结篇3之——生命周期和线程同步

    一.生命周期 线程的生命周期全在一张图中,理解此图是基本: 线程状态图 一.新建和就绪状态 当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时它和其他的Java对象一样,仅仅由Jav ...

  2. Java基础-多线程-③线程同步之synchronized

    使用线程同步解决多线程安全问题 上一篇 Java基础-多线程-②多线程的安全问题 中我们说到多线程可能引发的安全问题,原因在于多个线程共享了数据,且一个线程在操作(多为写操作)数据的过程中,另一个线程 ...

  3. 多线程,线程同步,synchronized关键字的用法

    一.什么是多线程 Java多线程实现方式主要有四种:继承Thread类.实现Runnable接口.实现Callable接口通过FutureTask包装器来创建Thread线程.使用ExecutorSe ...

  4. java多线程(2) 线程同步

    我们对线程访问同一份资源的多个线程之间,来进行协调的这个东西,就是线程同步.   例子1:模拟了多个线程操作同一份资源,可能带来的问题: package com.cy.thread; public c ...

  5. Java多线程之线程同步【synchronized、Lock、volatitle】

    线程同步 线程同步:当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态,实现线程同步的方法有很多. ...

  6. Delphi多线程详解

    (整理自网络) Delphi多线程处理 1-1多线程的基本概念 WIN 98/NT/2000/XP 是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用CPU 运行时间和资源,或者 ...

  7. 【转】Delphi多线程编程

    文章来源: http://liukun966123.my.gsdn.net/2004/10/22/4797/ Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书 ...

  8. delphi 多线程3

     多线程程序设计 我们知道,win95或winNT都是“多线程”的操作系统,在DELPHI .中,我们可以充分利用这一特性,编写出“多线程”的应用程序. 对以往在DOS或16位windows下写程序的 ...

  9. [转]Delphi多线程编程入门(二)——通过调用API实现多线程

    以下是一篇很值得看的关于Delphi多线程编程的文章,内容很全面,建议收藏. 一.入门 ㈠. function CreateThread(    lpThreadAttributes: Pointer ...

随机推荐

  1. react

    package.json ENOSPC 文件监控增加一些 echo fs.inotify.max_user_watches=582222 | sudo tee -a /etc/sysctl.conf ...

  2. Sed、Awk单行脚本快速参考

    文本间隔: # 在每一行后面增加一空行 sed G awk '{printf("%s\n\n",$0)}' # 将原来的所有空行删除并在每一行后面增加一空行. # 这样在输出的文本 ...

  3. zabbix安装

    在服务器10.128.17.136上安装 1.安装mysql \# yum -y install mysql mysql-server mysql-devel MySQL 配置文件/etc/my.cn ...

  4. ThinkphpCMF笔记

    1.模板js,css文件__PUBLIC__ <link href="__TMPL__Public/style.css" rel="stylesheet" ...

  5. JQuery+Ajax+Struts2+Hibernate 实现完整的登录注册

    写在最前: 下午有招聘会,不想去,总觉得没有准备好,而且都是一些不对口的公司,可是又静不下心来,就来写个博客. 最近在仿造一个书城的网站:http://www.yousuu.com ,UI直接拿来用, ...

  6. 一些关于angularJS的自己学习和开发过程中遇到的问题及解决办法

    这篇文章也许会不定时更新,主要记录这段时间内自己遇到的angularjs学习开发的一些问题的解决办法.本文以摘抄为主,主要目的还是将自己遇到的困惑在各个地方查到的解决办法的汇总,给自己留个备忘吧. 1 ...

  7. Selenium WebDriver Code

    Selenium WebDriver 用于模拟浏览器的功能,可以做网站测试用,也可以用来做crawler.我是用eclipse开发的,导入selenium-server-standalone-***. ...

  8. WebService初学

    作为一个初学者,在遇到新的知识点的时候,搞清这个知识点的名称含义,是有必要的.那什么是WebService呢? 顾名思义,它是一个运行在web上的服务.这个服务通过网络为我们的程序提供服务方法.类似一 ...

  9. Fiddler将笔记本设置代理,抓取手机网络请求包

    第一步:下载fiddler,下载地址:http://www.telerik.com/download/fiddler 第二步:安装fiddler,略过... 第三步:启动fiddler,启动后界面如下 ...

  10. [原创]jquery+css3打造一款ajax分页插件

    最近公司的项目将好多分页改成了ajax的前台分页以前写的分页插件就不好用了,遂重写一个 支持IE6+,但没有动画效果如果没有硬需求,个人认为没必要多写js让动画在这些浏览器中实现css3的动画本来就是 ...