[Delphi] 多线程编程
本篇简单介绍一下Delphi下多线程的编写
一、CreateThread
这个是最原始最基础的方法,利用Windows API来创建
function ThreadProc(param: LPVOID): DWORD; stdcall;
beginResult := 0;
end;varthreadId: TThreadID;
beginCreateThread(nil, 0, @ThreadProc, nil, 0, threadId);
end;
通过CreateThread来创建一个新线程,并执行给定的回调函数,回调函数签名参考微软官方手册:https://msdn.microsoft.com/zh-cn/f0dc203f-200e-42f1-940c-24e3fe080175
Delphi为了满足RTL自身功能需求,简单地包装了下CreateThread成为一个新的方法,它就是BeginThread
function ThreadProc(param: Pointer): Integer;
beginResult := 0;
end;varthreadId: TThreadID;
beginBeginThread(nil, 0, @ThreadProc, nil, 0, threadId);
end;
BeginThread内部依然是调用的CreateThread。最明显的一个区别是BeginThread的回调函数没有stcall标记。
最大的区别是对异常的处理,原始CreateThread中如果发生异常,整个程序就默默地退出,而BeginThread创建的线程异常的话,会被默认的异常处理程序捕获,它退出时起码会弹个窗告诉你一声
function ThreadProc1(param: LPVOID): DWORD; stdcall;
beginraise Exception.Create('Error Message');Result := 0;
end;function ThreadProc2(param: Pointer): Integer;
beginraise Exception.Create('Error Message');Result := 0;
end;varthreadId: TThreadID;
begin//CreateThread(nil, 0, @ThreadProc1, nil, 0, threadId);BeginThread(nil, 0, @ThreadProc2, nil, 0, threadId);
end;
BeginThread详细说明见官方文档:http://docwiki.embarcadero.com/Libraries/Tokyo/en/System.BeginThread
二、TThread类
上面介绍的方法自然是比较底层比较C Style。Delphi提供了TThread这个类,只要继承它实现一个方法即可,用class的方式更OOP
typeTMyThread = class(TThread)protectedprocedure Execute; override;end;procedure TMyThread.Execute;
beginOutputDebugString('TMyThread.Execute()');
end;// 调用
vart: TThread;
begint := TMyThread.Create(True); // True表示挂起线程,暂不启动。默认为Falset.FreeOnTerminate := True; // 表示线程执行完毕后自动Freet.Start; // 启动线程
end;
如果我们只是想在线程中执行一小段代码,无论方式一或者方式二都不是很优雅,要写很多代码。
更简单的方式是使用匿名线程
TThread.CreateAnonymousThread(procedurebeginOutputdebugString('匿名线程');end).Start;
TThread.CreateAnonymousThread是静态方法,给一个lambda函数即可。这个方法内部也仅仅是创建了一个叫TAnonymousThread的类返回而已,和我们上面的TMyThread做的事情是一样的。
三、线程池
前面两种方式都是这样的执行过程:创建线程 > 执行函数 > 销毁线程。
其中线程的创建和销毁是比较占用CPU资源的,为了解决效率问题,所以有了线程池的概念。线程池中有若干线程处于挂起状态,即拿即用,不会有频繁的创建、销毁过程,提高了执行效率,适合频繁调用线程的场景
procedure TForm1.Button1Click(Sender: TObject);
beginTThreadPool.Default.QueueWorkItem(procedurebeginOutputdebugString(PChar(Format('当前线程:%d', [GetCurrentThreadId])));end);
end;
TThreadPool.Default返回一个默认的线程池,QueueWorkItem添加一个任务请求,注意我的是请求,如果线程池的工作线程到达上限的话是需要等待的,这是池和普通CreateThread不同的一个地方。
点击按钮两次,看到IDE日志窗口
线程池中默认没有线程,只有在点击第一次时会新建一个线程,当我点击第二次时,由于上次的线程已经处于空闲状态,所以可以直接用,于是日志上没有"Thread Start"的消息了。
四、Task
Task本质上也是使用的线程池,但是提供了比ThreadPool更丰富的功能,Task是可控的
procedure TForm1.Button1Click(Sender: TObject);
vartask: ITask;
begintask := TTask.Create(procedurebeginOutputdebugString('11111');Sleep(2000);end);task.Start;task.Wait; // 等待任务结束OutputdebugString('22222');
end;
使用静态方法Run立即启动一个Task
procedure TForm1.Button1Click(Sender: TObject);
vartask: ITask;
begintask := TTask.Run(procedurebeginOutputdebugString('11111');Sleep(2000);end);task.Wait; // 等待任务结束OutputdebugString('22222');
end;
创建任务组也是可以的
procedure TForm1.Button1Click(Sender: TObject);
vartasks: array of ITask;
beginSetLength(tasks, 3);tasks[0] := TTask.Run(procedurebeginOutputdebugString('task 1');Sleep(2000);end);tasks[1] := TTask.Run(procedurebeginOutputdebugString('task 2');Sleep(2000);end);tasks[2] := TTask.Run(procedurebeginOutputdebugString('task 3');Sleep(2000);end);TTask.WaitForAll(tasks);OutputdebugString('22222');
end;
使用Future来获取任务返回值
procedure TForm1.Button1Click(Sender: TObject);
vartask: ITask;f: IFuture<Integer>;n: Integer;
beginf := TTask.Future<Integer>(function: IntegerbeginSleep(1000);Result := 5;end);n := f.Value; // 阻塞,等到任务执行完毕
end;
[Delphi] 多线程编程相关推荐
- Delphi 多线程编程(1)
本文的内容取自万一博客,并重新加以整理,在此留存仅仅是方便自己学习和查阅.所有代码均亲自测试 delphi7下测试有效.图片均为自己制作. 多线程应该是编程工作者的基础技能, 但这个基础我从来没学过, ...
- Delphi多线程编程基础入门
1. 概述 对于开发人员来说,多线程是必备的知识,但相对来说,也是比较难的知识点.Delphi是一门古老而优秀的编程语言,它对多线程的处理有一些特殊的地方,本文尝试做一些简单的讲解,可以当作Delph ...
- Delphi多线程编程中的技巧
1)创建线程 MsgThread := TMsgThread.Create(False) ; //创建并执行线程 MsgThread := TMsgThread.Create(True) ; // ...
- Delphi数据库编程一日通
Delphi数据库编程一日通. 通常情况下,利用 Delphi 开发数据库应用程序,可以使用TTable.TDataSource.TDBEdit.TDBNavigator等构件.只要正确设置了构件的某 ...
- Delphi多线程详解CreateThread、TThread,以及线程间通过临界区(CriticalSection)实现同步
在了解多线程之前我们先了解一下进程和线程的关系 一个程序至少有一个主进程,一个进程至少有一个线程. 为了保证线程的安全性请大家看看下面介绍 Delphi多线程同步的一些处理方案大家可以参考:ht ...
- delphi 多线程3
多线程程序设计 我们知道,win95或winNT都是"多线程"的操作系统,在DELPHI 2.0中,我们可以充分利用这一特性,编写出"多线程"的应用程序. 对 ...
- delphi多线程TThread类介绍
Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本上都是对TThread类的几个成员作一简单介绍,再说明一下Execute的实现和Synchr ...
- Delphi多线程详解
(整理自网络) Delphi多线程处理 1-1多线程的基本概念 WIN 98/NT/2000/XP 是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用CPU 运行时间和资源,或者 ...
- delphi 多线程详解及其详解例子
在了解多线程之前我们先了解一下进程和线程的关系 一个程序至少有一个主进程,一个进程至少有一个线程. 为了保证线程的安全性请大家看看下面介绍 Delphi多线程同步的一些处理方案大家可以参考:http: ...
最新文章
- 黑客发飙!智能汽车不太安全你还敢开?
- 互联网协议 — 使用 Wireshark 调试 HTTPS 及 HTTP/2 流量
- linux wifi关闭5g,TP-Link路由器如何关闭5G无线Wi-Fi信号?
- pt-archiver 数据归档bug
- 今日恐慌与贪婪指数为65 等级转为贪婪
- 刺客信条起源计算机内存不足,刺客信条起源需要什么配置能玩?最低/推荐配置需求介绍...
- python实现猜数字游戏
- mysql主从配置文件
- html5创建桌面快捷方式,iOS APP创建桌面快捷方式
- spss-多元线性回归分析
- 桥接模式---Bridge
- DirectShow Filter的开发实践
- 致谢词大全字C语言,C语言毕业论文致谢词范文
- 浏览器绑定快捷键KeyboardEvent
- 几个简单好用的APP分享给你
- C#窗体加标尺的两种方式及显现效果
- VESD联网防静电门禁管理系统有哪些功能?
- Excel从txt导入文本并将空行删除
- Python风险价值计算投资组合VaR、期望损失ES
- Flutter下MVVM——Bloc的探索
热门文章
- 指纹模块开发-FPW(M)指纹系列产品
- 【100%通过率】华为OD机试真题 JS 实现【最接近最大输出功率的设备 /查找充电设备组合】【2023 Q1 | 200分】
- 12 More Effective C++—条款16/17 (2/8原理与延缓求值)
- Android 常用图片框架对比
- 计算机系统基础实验 - 同符号浮点数加法运算/无符号定点数乘法运算的机器级表示
- 西蒙菲莎大学计算机研究性硕士,不只是知名大学:西蒙菲莎大学你需要知道这些!...
- iptables 之-m -state
- Oracle等数据库报盘步骤(使用脚本批量压缩)
- 服务器之间的无线通讯,无线通讯技术之间的比较 - 常见无线通信(数据)传输技术 你知道哪些...
- 偏移变色lisp_直线偏移联动 - AutoLISP/Visual LISP 编程技术 - CAD论坛 - 明经CAD社区 - Powered by Discuz!...