delphi 线程教学第三节:设计一个有生命力的工作线程
procedure TFooThread . Execute; begin // 0.挂起 while not Terminated do // Terminated 是 TThread 的一个 Boolean 属性。 begin // 1.获得参数 // 2.计算 // 3.返回结果 // 4.挂起 end ; end ; |
unit
uFooThread;
interface
uses
System
.
Classes, System
.
SyncObjs;
type
TFooThread =
class
(TThread)
private
FEvent: TEvent;
// 此类用来实现线程挂起功能
protected
procedure
Execute; override;
public
constructor
Create(CreateSuspended:
Boolean
);
destructor
Destroy; override;
procedure
StartThread;
// 设计线程的启动函数。
end
;
implementation
constructor
TFooThread
.
Create(CreateSuspended:
Boolean
);
begin
inherited
;
FEvent := TEvent
.
Create(
nil
,
true
,
false
,
''
);
// 默认让 FEvent 无信号
FreeOnTerminate :=
true
;
// True的意义是,代码退出 Execute 后,本类自动释放。
end
;
destructor
TFooThread
.
Destroy;
begin
FEvent
.
Free;
inherited
;
end
;
procedure
TFooThread
.
Execute;
begin
FEvent
.
WaitFor;
// 如果 FEvent 无信号,就一直等。
// 如果 FEvent 已被设置有信号,就退出 WaitFor ,解除阻塞。
// 这样,就实现了线程的挂起功能。
// 挂起是指线程时空的代码,停在了当前位置,就是 FEvent.WaitFor 这个位置。
FEvent
.
ResetEvent;
// 清除信号,以便下一次继续挂起。
while
not
Terminated
do
begin
// 1.获得参数
// 2.计算
// 3.返回结果
FEvent
.
WaitFor;
// 同上
FEvent
.
ResetEvent;
end
;
end
;
procedure
TFooThread
.
StartThread;
begin
FEvent
.
SetEvent;
// 所谓启动线程功能,就是要让 FEvent 有信号,让它解除阻塞。
end
;
end
.
// 线程正常退出示例
var
foo: TFooThread;
begin
foo := TFooThread
.
Create(
false
);
// false 是指创建后不挂起,直接运行 Execute 中的代码。
sleep(
1000
);
// 技术性代码,请忽略,但此处又不可少。
foo
.
Terminate;
// 此句的功能是 Terminated:=True;
// Terminated TThread 的一个 Boolean 属性
// 在 Execute 函数中我们用它做为退出循环的标志
// 请学习系统源码中的英语命名的方法,注意词性,时态。
// Terminate 是动词,是一个函数。而 Terminated 是过去分词,是一个属性。
foo
.
StartThread;
// 启动线程。
// FreeOnTerminated 已在 Create 函数中设置为 True 。
// 所以,代码退出 Execute 后,foo 会自动 free 的。
end
;
unit
uFooThread; // 用于计算的线程类
interface
uses
System
.
Classes, System
.
SyncObjs;
type
TFooThread =
class
;
TOnWorked =
procedure
(Sender: TFooThread)
of
object
;
TFooThread =
class
(TThread)
private
FEvent: TEvent;
protected
procedure
Execute; override;
public
constructor
Create(CreateSuspended:
Boolean
);
destructor
Destroy; override;
procedure
StartThread;
public
Num:
integer
;
Total:
integer
;
OnWorked: TOnWorked;
end
;
implementation
constructor
TFooThread
.
Create(CreateSuspended:
Boolean
);
begin
inherited
;
FEvent := TEvent
.
Create(
nil
,
true
,
false
,
''
);
FreeOnTerminate :=
true
;
end
;
destructor
TFooThread
.
Destroy;
begin
FEvent
.
Free;
inherited
;
end
;
procedure
TFooThread
.
Execute;
var
i:
integer
;
begin
FEvent
.
WaitFor;
FEvent
.
ResetEvent;
while
not
Terminated
do
begin
Total :=
0
;
if
Num >
0
then
begin
for
i :=
1
to
Num
do
begin
Total := Total + i;
sleep(
10
);
//故意让线程耗时,以达到更好的演示效果。
end
;
end
;
if
Assigned(OnWorked)
then
OnWorked(self);
FEvent
.
WaitFor;
FEvent
.
ResetEvent;
end
;
end
;
procedure
TFooThread
.
StartThread;
begin
FEvent
.
SetEvent;
end
;
end
.
unit
Unit11; //在窗口中调用
interface
uses
Winapi
.
Windows, Winapi
.
Messages, System
.
SysUtils, System
.
Variants, System
.
Classes, Graphics,
Vcl
.
Controls, Vcl
.
Forms, Vcl
.
Dialogs, Vcl
.
StdCtrls, uFooThread;
type
TForm11 =
class
(TForm)
Memo1: TMemo;
Button1: TButton;
Edit1: TEdit;
procedure
FormCreate(Sender: TObject);
procedure
Button1Click(Sender: TObject);
procedure
FormDestroy(Sender: TObject);
private
{ Private declarations }
FooThread: TFooThread;
procedure
OnWorked(Sender: TFooThread);
// 用来接收线程的 OnWorked 事件。
// 取名是任意的,只要参数相同。
// 如果你也可以取名为 procedure OnFininshed (O:TFooThread); 同样有效。
public
{ Public declarations }
end
;
var
Form11: TForm11;
implementation
{
$R
*.dfm}
// 本例为了照顾初学者,未对控件取正确的名字。
// 以后的章节中,将全部采用合理的命名,且提供源码下载地址。
procedure
TForm11
.
Button1Click(Sender: TObject);
var
n:
integer
;
begin
Button1
.
Enabled :=
false
;
// 禁用此 button ,以防线程运行期间误点
// 这是很重要的!用了线程,就要对所有的情况负责。
// button 被禁用后,在线程计算完成的事件中,将恢复
// 就可以继续点击它了。
n := StrToIntDef(Edit1
.
Text,
0
);
FooThread
.
Num := n;
FooThread
.
StartThread;
end
;
procedure
TForm11
.
FormCreate(Sender: TObject);
begin
FooThread := TFooThread
.
Create(
false
);
FooThread
.
OnWorked := self
.
OnWorked;
// 如果按另一个定义的名字也可以写:
// FooThread.OnWorked:=self.OnFininished;
end
;
procedure
TForm11
.
FormDestroy(Sender: TObject);
begin
FooThread
.
Terminate;
FooThread
.
StartThread;
// 释放线程。此处不是很严谨,以后章节的代码中将完善它。
end
;
procedure
TForm11
.
OnWorked(Sender: TFooThread);
var
s:
string
;
begin
s := IntToStr(Sender
.
Num);
s := s +
'的累加和为:'
;
s := s + IntToStr(Sender
.
Total);
// 此处是线程时空,操作 UI 要用 Synchronize;
TThread
.
Synchronize(
nil
,
procedure
begin
Memo1
.
Lines
.
Add(s); //匿名函数,可以用外部的变量(s)。这是很高级的特性。
Button1
.
Enabled :=
true
;
//恢复按钮,以便继续使用。
end
);
// 此处还可以作为继续启动线程的入口,下一章节会讲解。
end
;
end
.
delphi 线程教学第三节:设计一个有生命力的工作线程的更多相关文章
- delphi 线程教学第二节:在线程时空中操作界面(UI)
第二节:在线程时空中操作界面(UI) 1.为什么要用 TThread ? TThread 基于操作系统的线程函数封装,隐藏了诸多繁琐的细节. 适合于大部分情况多线程任务的实现.这个理由足够了吧 ...
- WPF 多线程 UI:设计一个异步加载 UI 的容器
对于 WPF 程序,如果你有某一个 UI 控件非常复杂,很有可能会卡住主 UI,给用户软件很卡的感受.但如果此时能有一个加载动画,那么就不会感受到那么卡顿了.UI 的卡住不同于 IO 操作或者密集的 ...
- 一个使用高并发高线程数 Server 使用异步数据库客户端造成的超时问题
现象 今天在做一个项目时, 将 tomcat 的 maxThreads 加大, 加到了 1024, tomcat 提供的服务主要是做一些运算, 然后插入 redis, 查询 redis, 最后将任务返 ...
- 使用C++11实现一个半同步半异步线程池
前言 C++11之前我们使用线程需要系统提供API.posix线程库或者使用boost提供的线程库,C++11后就加入了跨平台的线程类std::thread,线程同步相关类std::mutex.std ...
- 简单分析ThreadPoolExecutor回收工作线程的原理
最近阅读了JDK线程池ThreadPoolExecutor的源码,对线程池执行任务的流程有了大体了解,实际上这个流程也十分通俗易懂,就不再赘述了,别人写的比我好多了. 不过,我倒是对线程池是如何回收工 ...
- 分布式缓存系统 Memcached 工作线程初始化
Memcached采用典型的Master-Worker模式,其核心思想是:有Master和Worker两类进程(线程)协同工作,Master进程负责接收和分配任务,Worker进程负责处理子任务.当各 ...
- JAVA之工作线程数究竟要设置多少
一.需求缘起 Web-Server通常有个配置,最大工作线程数,后端服务一般也有个配置,工作线程池的线程数量,这个线程数的配置不同的业务架构师有不同的经验值,有些业务设置为CPU核数的2倍,有些业务设 ...
- delphi 线程教学第七节:在多个线程时空中,把各自的代码塞到一个指定的线程时空运行
第七节:在多个线程时空中,把各自的代码塞到一个指定的线程时空运行 以 Ado 为例,常见的方法是拖一个 AdoConnection 在窗口上(或 DataModule 中), 再配合 AdoQ ...
- delphi 线程教学第六节:TList与泛型
第六节: TList 与泛型 TList 是一个重要的容器,用途广泛,配合泛型,更是如虎添翼. 我们先来改进一下带泛型的 TList 基类,以便以后使用. 本例源码下载(delphi XE8版本) ...
随机推荐
- C#窗体互动
说白了就是在一个窗体操作另外一个窗体的东西. 原理是把form2的数据提取出来,利用中间的静态类middle来传递数据,触发事件,调用委托,来修正form1 效果如下: Form1.cs usin ...
- 中国移动OnetNet云平台 GET指令使用
GET /devices//datastreams/KEY HTTP/1.1 Host: api.heclouds.com api-key: pmWLtnkDBSreKfvg7GsClUXdXa4A ...
- STM32 ~ MDK环境下调试程序 HardFault_Handler 相关
STM32出现HardFault_Handler故障的原因主要有两个方面: 1.内存溢出或者访问越界.这个需要自己写程序的时候规范代码,遇到了需要慢慢排查. 2.堆栈溢出.增加堆栈的大小. 出现问题时 ...
- LeetCode:颜色分类【75】
LeetCode:颜色分类[75] 题目描述 给定一个包含红色.白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色.白色.蓝色顺序排列. 此题中,我们使用整数 ...
- HDU - 1175 连连看 【DFS】【BFS】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1175 思路 这种题一想到就用搜索, 但是内存是32m 用 bfs 会不会MLE 没错 第一次 BFS的 ...
- 培训笔记——Linux历史
1. 计算机有分时与实时操作系统的区分,如Dos为实时操作系统,你只能给它下达一个命令,这个命令执行完了,你才能下达下一个命令:像Linux和我们用的Windows就是分时操作系统,特点是可以并发 ...
- vim设置tab为4空格
vim的最基础设置 vim的设置需要编辑~/.vimrc文件,更改已有设置或者在后面添加相应的设置. 设置tab为4字符 # ts: tabstop set ts=4 将tab展开为空格 # expa ...
- [java]final关键字、finally关键字与finalize()方法
final关键字: final关键字通常指的是“无法改变的”,使用“无法改变”这样修饰可能出于两个原因:设计或者效率. final可以修饰变量.方法和类. 一.final变量 一个既是static又是 ...
- ELK初步指南
ELK的简单科普文章,加入了自己的一些理解. 内容包括ELK的基本介绍, 应用场景, 架构设计, 监控及自监控, 业界进展及推荐资料等. 用户故事 场景一 作为一个运维工程师, 某天虚拟机出现故障, ...
- keeplive使用
一.简介 Keepalived是一个免费开源的,用C编写的类似于layer3, 4 & 7交换机制软件,具备我们平时说的第3层.第4层和第7层交换机的功能.主要提供loadbalancing( ...