【delphi】多线程与多线程同步
在 Delphi 中使用多线程有两种方法: 调用 API、使用 TThread 类;
使用 API 的代码更简单.
CreateThread
function CreateThread(
lpThreadAttributes: Pointer; {安全设置}
dwStackSize: DWORD; {堆栈大小}
lpStartAddress: TFNThreadStartRoutine; {入口函数}
lpParameter: Pointer; {函数参数}
dwCreationFlags: DWORD; {启动选项}
var lpThreadId: DWORD {输出线程 ID }
): THandle; stdcall; {返回线程句柄}
CreateThread 第三个参数是函数指针, 新线程建立后将立即执行该函数, 函数执行完毕, 系统将销毁此线程从而结束多线程的故事.
CreateThread 要使用的函数是系统级别的, 不能是某个类(譬如: TForm1)的方法, 并且有严格的格式(参数、返回值)要求, 不管你暂时是不是需要都必须按格式来;
因为是系统级调用, 还要缀上 stdcall, stdcall 是协调参数顺序的, 虽然这里只有一个参数没有顺序可言, 但这是使用系统函数的惯例.
CreateThread 还需要一个 var 参数来接受新建线程的 ID, 尽管暂时没用, 但这也是格式;
代码注释:
- 当前程序是一个进程, 进程只是一个工作环境, 线程是工作者;
- 每个进程都会有一个启动线程(或叫主线程), 也就是说: 大量的编码都是写给这个主线程的;
- ExitThread(0); 退出主线程;
- 系统不允许一个没有线程的进程存在, 所以程序就退出了.
- ExitThread 函数的参数是一个退出码, 这个退出码是给之后的其他函数用的, 这里随便给个无符号整数即可.
输出线程 ID
CreateThread 的最后一个参数是 "线程的 ID";
在主线程中 GetCurrentThreadId、MainThreadID、MainInstance 都可以获取主线程的ID.
启动选项
CreateThread 的倒数第二个参数 dwCreationFlags(启动选项) 有两个可选值:
- 0: 线程建立后立即执行入口函数;
- CREATE_SUSPENDED: 线程建立后会挂起等待.
可用 ResumeThread 函数是恢复线程的运行; 可用 SuspendThread 再次挂起线程.
这两个函数的参数都是线程句柄, 返回值是执行前的挂起计数.
挂起记数
SuspendThread 会给这个数 +1; ResumeThread 会给这个数 -1; 但这个数最小是 0.
当这个数 = 0 时, 线程会运行; > 0 时会挂起.
如果被 SuspendThread 多次, 同样需要 ResumeThread 多次才能恢复线程的运行.
多线程示例

//上面图片中演示的代码。
unit Unit1; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls; type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
end; var
Form1: TForm1; implementation {$R *.dfm} var
hThread: THandle; {线程句柄}
num: Integer; {全局变量, 用于记录随机数} {线程入口函数}
function MyThreadFun(p: Pointer): Integer; stdcall;
begin
while True do {假如线程不挂起, 这个循环将一直循环下去}
begin
num := Random();
end;
Result := ;
end; {建立并挂起线程}
procedure TForm1.Button1Click(Sender: TObject);
var
ID: DWORD;
begin
hThread := CreateThread(nil, , @MyThreadFun, nil, CREATE_SUSPENDED, ID);
Button1.Enabled := False;
end; {唤醒并继续线程}
procedure TForm1.Button2Click(Sender: TObject);
begin
ResumeThread(hThread);
end; {挂起线程}
procedure TForm1.Button3Click(Sender: TObject);
begin
SuspendThread(hThread);
end; procedure TForm1.FormCreate(Sender: TObject);
begin
Timer1.Interval := ;
end; procedure TForm1.Timer1Timer(Sender: TObject);
begin
Text := IntToStr(num);
end; end.
多线程同步
"临界区"(CriticalSection): 当把一段代码放入一个临界区, 线程执行到临界区时就独占了, 让其他也要执行此代码的线程先等等;
使用格式如下:
var CS: TRTLCriticalSection; {声明一个 TRTLCriticalSection 结构类型变量; 它应该是全局的}
InitializeCriticalSection(CS); {初始化}
EnterCriticalSection(CS); {开始: 轮到我了其他线程走开}
LeaveCriticalSection(CS); {结束: 其他线程可以来了}
DeleteCriticalSection(CS); {删除: 注意不能过早删除}
多线程同步示例

unit Unit1; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls; type
TForm1 = class(TForm)
ListBox1: TListBox;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
end; var
Form1: TForm1; implementation {$R *.dfm} var
CS: TRTLCriticalSection; function MyThreadFun(p: Pointer): DWORD; stdcall;
var
i: Integer;
begin
EnterCriticalSection(CS);
for i := to do Form1.ListBox1.Items.Add(IntToStr(i));
LeaveCriticalSection(CS);
Result := ;
end; procedure TForm1.Button1Click(Sender: TObject);
var
ID: DWORD;
begin
CreateThread(nil, , @MyThreadFun, nil, , ID);
CreateThread(nil, , @MyThreadFun, nil, , ID);
CreateThread(nil, , @MyThreadFun, nil, , ID);
end; procedure TForm1.FormCreate(Sender: TObject);
begin
ListBox1.Align := alLeft;
InitializeCriticalSection(CS);
end; procedure TForm1.FormDestroy(Sender: TObject);
begin
DeleteCriticalSection(CS);
end; end.
参考文章
http://www.cnblogs.com/gzcszzx/articles/2110675.html
【delphi】多线程与多线程同步的更多相关文章
- C#多线程之线程同步篇3
在上一篇C#多线程之线程同步篇2中,我们主要学习了AutoResetEvent构造.ManualResetEventSlim构造和CountdownEvent构造,在这一篇中,我们将学习Barrier ...
- C#多线程之线程同步篇2
在上一篇C#多线程之线程同步篇1中,我们主要学习了执行基本的原子操作.使用Mutex构造以及SemaphoreSlim构造,在这一篇中我们主要学习如何使用AutoResetEvent构造.Manual ...
- C#多线程之线程同步篇1
在多线程(线程同步)中,我们将学习多线程中操作共享资源的技术,学习到的知识点如下所示: 执行基本的原子操作 使用Mutex构造 使用SemaphoreSlim构造 使用AutoResetEvent构造 ...
- 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLock
[源码下载] 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLoc ...
- 重新想象 Windows 8 Store Apps (47) - 多线程之线程同步: Semaphore, CountdownEvent, Barrier, ManualResetEvent, AutoResetEvent
[源码下载] 重新想象 Windows 8 Store Apps (47) - 多线程之线程同步: Semaphore, CountdownEvent, Barrier, ManualResetEve ...
- Linux多线程编程——多线程与线程同步
多线程 使用多线程好处: 一.通过为每种事件类型的处理单独分配线程,可以简化处理异步事件的代码,线程处理事件可以采用同步编程模式,启闭异步编程模式简单 二.方便的通信和数据交换 由于进程之间具有独立的 ...
- C#简单多线程使用(同步和优先权)
题目: 麦当劳有两个做汉堡的厨师(工号:11,12)和三个销售人员(工号:21,22,23). 厨师生产汉堡,并负责将做好的汉堡放入货架,货架台大小有限,最多放6个汉堡,11和12不能同时往货架台上放 ...
- IOS 多线程,线程同步的三种方式
本文主要是讲述 IOS 多线程,线程同步的三种方式,更多IOS技术知识,请登陆疯狂软件教育官网. 一般情况下我们使用线程,在多个线程共同访问同一块资源.为保护线程资源的安全和线程访问的正确性. 在IO ...
- 关于Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇高质量的博文)
Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇质量高的博文) 前言:在学习多线程时,遇到了一些问题,这里我将这些问题都分享出来,同时也分享了几篇其他博客主的博客,并且将我个人的理解也分享 ...
随机推荐
- std::string begin end
std::string 的begin到end是不包含 ‘\0’的
- 树莓派SD卡制作,并成功启动
需要条件: 硬件部分: 1.SD卡一张(树莓派支持的) 2.树莓派3 B + 一个(其他的版本也是可以的,这里默3B+). 1.下载树莓派镜像(NOOBS_v1_9_2.zip) wget http: ...
- CentOS 开启防火墙 firewall ,mysql 远程访问
最近在阿里云服务器centos上安装了mysql数据库,默认是不开启远端访问功能,需要设置一下防火墙,在开放默认端口号 3306时提示FirewallD is not running,经过排查发现是防 ...
- 纯CSS兑现侧边栏/分栏高度自动相等(转)
这里直接介绍我认为的最佳的侧边栏/分栏高度自动相等方法.核心的CSS代码如下(数值不固定): margin-bottom:-3000px; padding-bottom:3000px; 再配合父标签的 ...
- 【Oracle】Oracle约束的总结
你对ORACLE约束的了解如何?比较模糊还是相当透彻?如果你对下面几个问题了如指掌的话,恭喜你,你已经对约束掌握得比较好了,不用看这篇文章了.ORACLE的约束有啥功能作用? 有哪些类型约束(不同版本 ...
- ASP.NET 5 RC 1:UrlRouting 设置(不包含MVC6的UrlRouting设置)
转自:http://habrahabr.ru/company/microsoft/blog/268037/?mobile=no 1.project.json { "version" ...
- AndroidStudio升级到2.3版本无法编译的解决方法
上周五as提示更新,于是为了体验新功能还在编码过程中就迫不及待的点击了更新,公司网很快,十几分钟就下载好,然后一重启就懵逼了,提示是否更改依赖版本到2.3以及升级gradle到3.3,点了确定就一直在 ...
- 跟我学SharePoint 2013视频培训课程——探索默认的列表和库(6)
课程简介 第6天,探索默认的列表和库. 视频 SharePoint 2013 交流群 41032413
- Proxy源代码分析——谈谈如何学习Linux网络编程
Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到, Linux和Windows这样的"傻瓜"操作系统(这里丝毫没有贬低Windows的意思,相反这应该 ...
- [转] Spring4.3.x 浅析xml配置的解析过程(6)——解析context命名空间之property-placeholder和property-override标签
在上一篇解析自定义命名空间的标签中,我们已经知道解析自定义命名空间的标签需要用到NamespaceHandler接口的实现类,并且知道spring是如何获取命名空间对应的命名空间处理器对象的.因此我们 ...