delphi 线程教学第三节:设计一个有生命力的工作线程
procedure TFooThread.Execute;begin // 0.挂起 while not Terminated do // Terminated 是 TThread 的一个 Boolean 属性。 begin // 1.获得参数 // 2.计算 // 3.返回结果 // 4.挂起 end;end; |
unit uFooThread;interfaceuses 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;implementationconstructor 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; // 用于计算的线程类interfaceuses 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;implementationconstructor 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; //在窗口中调用interfaceuses 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版本) ...
随机推荐
- git克隆远程分支
$ git branch –r 查看远程branch信息 $ git checkout origin/dev检出远程分支 $ git branch -a 查看所有分支,包括本地和远程 可以使用chec ...
- js hoisting
1.变量提升 var x = 2; function test(){ console.log(x) var x = 1; } ==>运行程序报错,在test()函数中,x被提升到了顶部声明,相当 ...
- 关于mosquitto_internal.h:40:25:#include <uuid/uuid.h> 致命错误的解决
一.安装mosquitto1.4的时候使用make的时候报以下错误: mosquitto_internal.h:40:25: 致命错误:openssl/ssl.h:没有那个文件或目录 #include ...
- 禁用chrome浏览器的cookie
Chrome: 1.打开chrome浏览器,点击右上角的“自定义和控制Google Chrome”按钮 2.在下拉菜单中选择设置 3.点击设置页底部的“显示高级设置...” 4.在隐私设置下,点击“内 ...
- ionic添加scss
Setup Sass Automatically 在进行以下操作之前要确保node比较新,以便正确安装node-sass 或 改用cnpm install node-sass安装(淘宝源) $ ion ...
- frontend-tools
收集整理好用的前端开发利器(Collect good front-end development tools ) 1.w3cplus前端工具 2.jsfiddle在线JS代码调试工具 3.w3cfun ...
- HDU - 1175 连连看 【DFS】【BFS】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1175 思路 这种题一想到就用搜索, 但是内存是32m 用 bfs 会不会MLE 没错 第一次 BFS的 ...
- HDU - 3081 Marriage Match II 【二分匹配】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意 有n对男女 女生去选男朋友 如果女生从来没和那个男生吵架 那么那个男生就可以当她男朋友 女 ...
- [原创]java WEB学习笔记17:关于中文乱码的问题 和 tomcat在eclipse中起动成功,主页却打不开
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- 【八】MongoDB管理之分片集群实践
MongoDB中集群有三种:主从复制.副本集.分片集群.目前副本集已经替代主从复制架构,成为官方建议采用的架构,而分片集群相较于前两种,更加复杂. 下面是生产环境中常用的分片集群架构: 我们知道,分片 ...