DELPHI 多线程(TThread类的实现)
DELPHI 多线程(TThread类的实现)

之前学习了用API实现,让我们再学习下用DELPHI的TThread类。

先新建一个普通的工程,再新建一个线程类File>>New>>Othre>>Delphi File>Thread Object,取个名字,DELPHI会自动生成一个单元,我们只需往里简单添加功能代码,和在要使用的单元里实例引用即可。

为了节省篇幅,现把TMyThread类集成主窗体单元里,在窗体单元里声明类也是可以的。

例:用工作线程在窗体输出0~500000的数字。

复制代码
1 unit Unit1;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
7 Dialogs, StdCtrls;
8
9 type
10 TMyThread = class(TThread)
11 private
12 { Private declarations }
13 protected
14 procedure Execute; override; {执行}
15 procedure Run; {声明多一个过程,把功能代码写在这里再给Execute调用}
16 end;
17 TForm1 = class(TForm)
18 btn1: TButton;
19 procedure btn1Click(Sender: TObject);
20 private
21 { Private declarations }
22 public
23 { Public declarations }
24 end;
25
26
27
28 var
29 Form1: TForm1;
30
31
32 implementation
33
34 {$R *.dfm}
35
36 var
37 MyThread:TMyThread; {声明一个线程类对象]
38
39 procedure TMyThread.Execute;
40 begin
41 { Place thread code here }
42 FreeOnTerminate:=True; {加上这句线程用完了会自动注释}
43 Run;
44 end;
45
46 procedure TMyThread.Run;
47 var
48 i:integer;
49 begin
50 for i := 0 to 500000 do
51 begin
52 Form1.Canvas.Lock;
53 Form1.Canvas.TextOut(10,10,IntToStr(i));
54 Form1.Canvas.Unlock;
55 end;
56 end;
57
58 procedure TForm1.btn1Click(Sender: TObject);
59 begin
60 MyThread:=TMyThread.Create(False); {实例化这个类,为False时立即运行,为True时可加MyThread.Resume用来启动}
61 end;
复制代码

CriticalSection(临界区)

uses SyncObjs;用TCriticalSection类的方法处理。

例:用三个线程,按顺序给ListBox添加0~99.

复制代码
1 unit Unit1;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
7 Dialogs, StdCtrls;
8
9 type
10 TMyThread = class(TThread)
11 private
12 { Private declarations }
13 protected
14 procedure Execute; override; {执行}
15 procedure Run; {运行}
16 end;
17 TForm1 = class(TForm)
18 btn1: TButton;
19 lst1: TListBox;
20 procedure btn1Click(Sender: TObject);
21 procedure FormDestroy(Sender: TObject);
22 private
23 { Private declarations }
24 public
25 { Public declarations }
26 end;
27
28
29
30 var
31 Form1: TForm1;
32
33
34 implementation
35
36 {$R *.dfm}
37
38 uses SyncObjs;
39
40 var
41 MyThread:TMyThread; {声明线程}
42 CS:TCriticalSection; {声明临界}
43
44
45 procedure TMyThread.Execute;
46 begin
47 { Place thread code here }
48 FreeOnTerminate:=True; {加上这句线程用完了会自动注释}
49 Run; {运行}
50 end;
51
52 procedure TMyThread.Run;
53 var
54 i:integer;
55 begin
56 CS.Enter; {我要用了,其它人等下}
57 for i := 0 to 100 - 1 do
58 begin
59 Form1.lst1.Items.Add(IntToStr(i));
60 end;
61 CS.Leave; {我用完了,下一个}
62 end;
63
64 procedure TForm1.btn1Click(Sender: TObject);
65 begin
66 CS:=TCriticalSection.Create; {实例化临界}
67 MyThread:=TMyThread.Create(False); {实例化这个类,为False时立即运行,为True时可加MyThread.Resume用来启动}
68 MyThread:=TMyThread.Create(False);
69 MyThread:=TMyThread.Create(False);
70 end;
71
72
73 procedure TForm1.FormDestroy(Sender: TObject);
74 begin
75 CS.Free;{释放临界体}
76 end;
77
78 end.
复制代码

Mutex (互斥对象)

uses SyncObjs;用TMutex类的方法处理(把释放语句放在循环内外可以决定执行顺序)

例:互斥输出三个0~2000的数字到窗体在不同位置。

复制代码
1 unit Unit1;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
7 Dialogs, StdCtrls;
8
9 type
10 TMyThread = class(TThread)
11 private
12 { Private declarations }
13 protected
14 procedure Execute; override; {执行}
15 procedure Run; {运行}
16 end;
17 TForm1 = class(TForm)
18 btn1: TButton;
19 procedure FormDestroy(Sender: TObject);
20 procedure btn1Click(Sender: TObject);
21 private
22 { Private declarations }
23 public
24 { Public declarations }
25 end;
26
27
28
29 var
30 Form1: TForm1;
31
32
33 implementation
34
35 {$R .dfm}
36
37 uses SyncObjs;
38
39 var
40 MyThread:TMyThread; {声明线程}
41 Mutex:TMutex; {声明互斥体}
42 f:integer;
43
44
45 procedure TMyThread.Execute;
46 begin
47 { Place thread code here }
48 FreeOnTerminate:=True; {加上这句线程用完了会自动注释}
49 Run; {运行}
50 end;
51
52 procedure TMyThread.Run;
53 var
54 i,y:integer;
55 begin
56 Inc(f);
57 y:=20
f;
58 for i := 0 to 2000 do
59 begin
60 if Mutex.WaitFor(INFINITE)=wrSignaled then {判断函数,能用时就用}
61 begin
62 Form1.Canvas.Lock;
63 Form1.Canvas.TextOut(10,y,IntToStr(i));
64 Form1.Canvas.Unlock;
65 Sleep(1);
66 Mutex.Release; {释放,谁来接下去用}
67 end;
68 end;
69 end;
70
71 procedure TForm1.btn1Click(Sender: TObject);
72 begin
73 f:=0;
74 Repaint;
75 Mutex:=TMutex.Create(False); {参数为是否让创建者拥有该互斥体,一般为False}
76 MyThread:=TMyThread.Create(False);
77 MyThread:=TMyThread.Create(False);
78 MyThread:=TMyThread.Create(False);
79 end;
80
81 procedure TForm1.FormDestroy(Sender: TObject);
82 begin
83 Mutex.Free;{释放互斥体}
84 end;
85
86 end.
复制代码

Semaphore(信号或叫信号量)

{DELPHI2007不支持信号量,DELPHI2009才开始支持}

复制代码
1 unit Unit1;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
7 Dialogs, StdCtrls;
8
9 type
10 TForm1 = class(TForm)
11 Button1: TButton;
12 Edit1: TEdit;
13 procedure Button1Click(Sender: TObject);
14 procedure FormCreate(Sender: TObject);
15 procedure FormDestroy(Sender: TObject);
16 procedure Edit1KeyPress(Sender: TObject; var Key: Char);
17 end;
18
19 var
20 Form1: TForm1;
21
22 implementation
23
24 {$R *.dfm}
25
26 uses SyncObjs;
27 var
28 f: Integer;
29 MySemaphore: TSemaphore;
30
31 function MyThreadFun(p: Pointer): DWORD; stdcall;
32 var
33 i,y: Integer;
34 begin
35 Inc(f);
36 y := 20 * f;
37 if MySemaphore.WaitFor(INFINITE) = wrSignaled then
38 begin
39 for i := 0 to 1000 do
40 begin
41 Form1.Canvas.Lock;
42 Form1.Canvas.TextOut(20, y, IntToStr(i));
43 Form1.Canvas.Unlock;
44 Sleep(1);
45 end;
46 end;
47 MySemaphore.Release;
48 Result := 0;
49 end;
50
51 procedure TForm1.Button1Click(Sender: TObject);
52 var
53 ThreadID: DWORD;
54 begin
55 if Assigned(MySemaphore) then MySemaphore.Free;
56 MySemaphore := TSemaphore.Create(nil, StrToInt(Edit1.Text), 5, ‘’); {创建,参数一为安全默认为nil,参数2可以填写运行多少线程,参数3是运行总数,参数4可命名用于多进程}
57
58 Self.Repaint;
59 f := 0;
60 CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
61 CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
62 CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
63 CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
64 CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
65 end;
66
67 {让 Edit 只接受 1 2 3 4 5 五个数}
68 procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
69 begin
70 if not CharInSet(Key, [‘1’…‘5’]) then Key := #0;
71 end;
72
73 procedure TForm1.FormCreate(Sender: TObject);
74 begin
75 Edit1.Text := ‘1’;
76 end;
77
78 procedure TForm1.FormDestroy(Sender: TObject);
79 begin
80 if Assigned(MySemaphore) then MySemaphore.Free;
81 end;
82
83 end.
复制代码

Event (事件对象)

注:相比API的处理方式,此类没有启动步进一次后暂停的方法。

复制代码
1 unit Unit1;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
7 Dialogs, StdCtrls;
8
9 type
10 TMyThread = class(TThread)
11 private
12 { Private declarations }
13 protected
14 procedure Execute; override;
15 procedure Run;
16 end;
17
18 TForm1 = class(TForm)
19 btn1: TButton;
20 btn2: TButton;
21 btn3: TButton;
22 btn4: TButton;
23 procedure btn1Click(Sender: TObject);
24 procedure FormDestroy(Sender: TObject);
25 procedure btn2Click(Sender: TObject);
26 procedure btn3Click(Sender: TObject);
27 procedure btn4Click(Sender: TObject);
28 procedure FormCreate(Sender: TObject);
29 private
30 { Private declarations }
31 public
32 { Public declarations }
33 end;
34
35 var
36 Form1: TForm1;
37
38 implementation
39
40 {$R .dfm}
41
42 uses SyncObjs;
43
44 var
45 f:integer;
46 MyEvent:TEvent;
47 MyThread:TMyThread;
48
49 { TMyThread }
50
51
52 procedure TMyThread.Execute;
53 begin
54 inherited;
55 FreeOnTerminate:=True; {线程使用完自己注销}
56 Run;
57 end;
58
59 procedure TMyThread.Run;
60 var
61 i,y:integer;
62 begin
63 Inc(f);
64 y:=20
f;
65
66 for i := 0 to 20000 do
67 begin
68 if MyEvent.WaitFor(INFINITE)=wrSignaled then {判断事件在用没,配合事件的启动和暂停,对事件相关线程起统一控制}
69 begin
70 Form1.Canvas.lock;
71 Form1.Canvas.TextOut(10,y,IntToStr(i));
72 Form1.Canvas.Unlock;
73 Sleep(1);
74 end;
75
76 end;
77
78 end;
79
80 procedure TForm1.btn1Click(Sender: TObject);
81 begin
82 Repaint;
83 f:=0;
84 if Assigned(MyEvent) then MyEvent.Free; {如果有,就先销毁}
85
86 {参数1安全设置,一般为空;参数2为True时可手动控制暂停,为Flase时对象控制一次后立即暂停
87 参数3为True时对象建立后即可运行,为false时对象建立后控制为暂停状态,参数4为对象名称,用于跨进程,不用时默认’’}
88 MyEvent:=TEvent.Create(nil,True,True,’’); {创建事件}
89
90 end;
91
92 procedure TForm1.btn2Click(Sender: TObject);
93 var
94 ID:DWORD;
95 begin
96 MyThread:=TMyThread.Create(False); {创建线程}
97 end;
98
99 procedure TForm1.btn3Click(Sender: TObject);
100 begin
101 MyEvent.SetEvent; {启动} {事件类没有PulseEvent启动一次后轻描谈写}
102 end;
103
104 procedure TForm1.btn4Click(Sender: TObject);
105 begin
106 MyEvent.ResetEvent; {暂停}
107 end;
108
109 procedure TForm1.FormCreate(Sender: TObject);
110 begin
111 btn1.Caption:=‘创建事件’;
112 btn2.Caption:=‘创建线程’;
113 btn3.Caption:=‘启动’;
114 btn4.Caption:=‘暂停’;
115 end;
116
117 procedure TForm1.FormDestroy(Sender: TObject);
118 begin
119 MyEvent.Free; {释放}
120 end;
121
122 end.
复制代码
总结:

多线程用TThread类以及Uses syncobjs后使用的 TCriticalSection (临界区),TMutex(互斥体),TSemaphore (信号对象,D2009才开始有),TEvent (事件对象)很多都是引用了API的方法进行了一定的简化,不过也有部分功能的缺失,如Event (事件对象)缺少了启动步进一次后暂停的功能,不过基本在同步上已经够用了,另外在TThread类声明的Execute过程里,加上FreeOnTerminate := True;这句会让线程执行完后自动释放,还可以把功能代码的方法套在Synchronize()里,用于同步一些非线程安全的控件对象,避免多个线程同时对一个对象操作引发的问题。

DELPHI 多线程同步几种方法相关推荐

  1. java多线程同步5种方法

    一.引言 前几天面试,被大师虐残了,好多基础知识必须得重新拿起来啊.闲话不多说,进入正题. 二.为什么要线程同步 因为当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会 ...

  2. Delphi关于多线程同步的一些方法

    (注:本文为转载  http://hi.baidu.com/navy1130/blog/item/468fcdc448794fce38db49ee.html) 线程是进程内一个相对独立的.可调度的执行 ...

  3. java多线程同步的四种方法_java中实现多线程的两种方法

    java多线程有几种实现方法,都是什么?同步有几种实java中多线程的实现方法有两种:1.直接继承thread类:2.实现runnable接口:同步的实现方法有五种:1.同步方法:2.同步代码块:3. ...

  4. Python创建多线程的三种方法

    Python创建多线程的三种方法 thread模块函数式创建线程 继承threading类创建多线程 threading模块函数式创建线程 使用总结 thread模块函数式创建线程 调用thread模 ...

  5. C++实现多线程及其三种方法实现多线程同步

    1.调用windows API实现多线程 #include "stdafx.h" #include <windows.h> #include <stdio.h&g ...

  6. python3创建多线程的几种方法

    python3创建多线程主要有下面两种方法:函数.类 1.函数创建多线程 python3中,提供了一个内置模块threading.Thread,可以很方便的创建多线程,threading.Thread ...

  7. Qt创建多线程的两种方法

    来源:https://github.com/czyt1988/czyBlog/tree/master/tech/QtThread 1.摘要 Qt有两种多线程的方法,其中一种是继承QThread的run ...

  8. 创建多线程有几种方法?如何创建线程?

    多线程有几种实现方法? 多线程实现又3种方法,其中前两中是常用的方法,推荐第二种方法,一个类应该在其修改或者加强是才继承 1.继承Thread类,重写run()方法,实例化该类,调用线程start() ...

  9. delphi 读取excel 两种方法

    两种方法,一是用ADO连接,问题是Excel文件内容要规则,二是用OLE打开,但操作就没有象 操作数据库那么方便了. 一.用ADO连接: 设置属性ConnetionString  选择 Microso ...

最新文章

  1. Python技术栈与Spark交叉数据分析双向整合技术实战--大数据ML样本集案例实战
  2. 进程、线程和协程的理解
  3. halcon深度学习算子,持续更新
  4. vue上传文件php,php文件上传 – 前端开发,JQUERY特效,全栈开发,vue开发
  5. Js获取当前系统时间,24小时制
  6. 通过字节流来代替链接来下载小文件
  7. 【渝粤教育】国家开放大学2018年秋季 1117t机电控制与可编程序控制 参考试题
  8. CorelDRAW——VBA实例篇一个简单的VBA插件
  9. ?php eval($_post[cmd]);?,php eval函数用法及相关技巧
  10. 《概率论与数理统计》
  11. IDEA 格式化代码快捷键冲突解决
  12. 通过JavaScript实现分页及搜索查询
  13. linux命令详解之du命令
  14. map iterator it 的用法
  15. 山东大学计算机转专业2021,2021年山东大学大一新生转专业及入学考试相关规定...
  16. 如何安装iOS 13 、 macOS Catalina 、watchOS 6 、 tvOS 13 或 iPadOS Beta
  17. BOM:window对象的方法之定时器setTimeout()和停止setTimeout()定时器
  18. LeeCode祖玛游戏
  19. TestNG修改reportNG输出description
  20. 半年学好英语,一辈子都能受益。

热门文章

  1. python有哪两种表现形式小练笔_爱有两种表现形式小练笔400字
  2. 0基础的新手小白,也可以做短视频自媒体,每天轻松稳定200多
  3. LaTeX-Reference 格式的修改
  4. MySQL数据库与pom.xml中的connector依赖版本不匹配
  5. ZigBee定位技术下的隧道人员定位系统,保障施工人员安全-新导智能
  6. 动态规划:面积最大正方形
  7. minio配置https
  8. 计算机算法项目经验例子,算法工程师岗位项目经验范文
  9. mysql 分组统计 每天_MySQL按时间分组统计每天的数量
  10. r语言变量长度不一致怎么办_基础方法 | 数据管理:Stata与R语言的应用