本篇简单介绍一下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] 多线程编程相关推荐

  1. Delphi 多线程编程(1)

    本文的内容取自万一博客,并重新加以整理,在此留存仅仅是方便自己学习和查阅.所有代码均亲自测试 delphi7下测试有效.图片均为自己制作. 多线程应该是编程工作者的基础技能, 但这个基础我从来没学过, ...

  2. Delphi多线程编程基础入门

    1. 概述 对于开发人员来说,多线程是必备的知识,但相对来说,也是比较难的知识点.Delphi是一门古老而优秀的编程语言,它对多线程的处理有一些特殊的地方,本文尝试做一些简单的讲解,可以当作Delph ...

  3. Delphi多线程编程中的技巧

    1)创建线程  MsgThread := TMsgThread.Create(False) ; //创建并执行线程  MsgThread := TMsgThread.Create(True) ; // ...

  4. Delphi数据库编程一日通

    Delphi数据库编程一日通. 通常情况下,利用 Delphi 开发数据库应用程序,可以使用TTable.TDataSource.TDBEdit.TDBNavigator等构件.只要正确设置了构件的某 ...

  5. Delphi多线程详解CreateThread、TThread,以及线程间通过临界区(CriticalSection)实现同步

     在了解多线程之前我们先了解一下进程和线程的关系 一个程序至少有一个主进程,一个进程至少有一个线程. 为了保证线程的安全性请大家看看下面介绍 Delphi多线程同步的一些处理方案大家可以参考:ht ...

  6. delphi 多线程3

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

  7. delphi多线程TThread类介绍

    Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本上都是对TThread类的几个成员作一简单介绍,再说明一下Execute的实现和Synchr ...

  8. Delphi多线程详解

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

  9. delphi 多线程详解及其详解例子

    在了解多线程之前我们先了解一下进程和线程的关系 一个程序至少有一个主进程,一个进程至少有一个线程. 为了保证线程的安全性请大家看看下面介绍 Delphi多线程同步的一些处理方案大家可以参考:http: ...

最新文章

  1. 黑客发飙!智能汽车不太安全你还敢开?
  2. 互联网协议 — 使用 Wireshark 调试 HTTPS 及 HTTP/2 流量
  3. linux wifi关闭5g,TP-Link路由器如何关闭5G无线Wi-Fi信号?
  4. pt-archiver 数据归档bug
  5. 今日恐慌与贪婪指数为65 等级转为贪婪
  6. 刺客信条起源计算机内存不足,刺客信条起源需要什么配置能玩?最低/推荐配置需求介绍...
  7. python实现猜数字游戏
  8. mysql主从配置文件
  9. html5创建桌面快捷方式,iOS APP创建桌面快捷方式
  10. spss-多元线性回归分析
  11. 桥接模式---Bridge
  12. DirectShow Filter的开发实践
  13. 致谢词大全字C语言,C语言毕业论文致谢词范文
  14. 浏览器绑定快捷键KeyboardEvent
  15. 几个简单好用的APP分享给你
  16. C#窗体加标尺的两种方式及显现效果
  17. VESD联网防静电门禁管理系统有哪些功能?
  18. Excel从txt导入文本并将空行删除
  19. Python风险价值计算投资组合VaR、期望损失ES
  20. Flutter下MVVM——Bloc的探索

热门文章

  1. 指纹模块开发-FPW(M)指纹系列产品
  2. 【100%通过率】华为OD机试真题 JS 实现【最接近最大输出功率的设备 /查找充电设备组合】【2023 Q1 | 200分】
  3. 12 More Effective C++—条款16/17 (2/8原理与延缓求值)
  4. Android 常用图片框架对比
  5. 计算机系统基础实验 - 同符号浮点数加法运算/无符号定点数乘法运算的机器级表示
  6. 西蒙菲莎大学计算机研究性硕士,不只是知名大学:西蒙菲莎大学你需要知道这些!...
  7. iptables 之-m -state
  8. Oracle等数据库报盘步骤(使用脚本批量压缩)
  9. 服务器之间的无线通讯,无线通讯技术之间的比较 - 常见无线通信(数据)传输技术 你知道哪些...
  10. 偏移变色lisp_直线偏移联动 - AutoLISP/Visual LISP 编程技术 - CAD论坛 - 明经CAD社区 - Powered by Discuz!...