如何实现多线程编程的基础概念?

2026-05-27 17:281阅读0评论SEO教程
  • 内容介绍
  • 相关推荐

本文共计937个文字,预计阅读时间需要4分钟。

如何实现多线程编程的基础概念?

编写一个循环程序,执行50000次,每次在程序界面的左上方(10,10)位置输出数字,代码如下:

pascalprocedure TForm1.btn2Click(Sender: TObject);var i: Integer;begin for i :=0 to 50000 do begin Writeln(10, 10, i); end;end;

先编写一个循环 50000 次的程序,每次在程序界面左上方(10,10)的位置输出数字,代码如下:

1 procedure TForm1.btn2Click(Sender: TObject); 2 var 3 i: Integer; 4 begin 5 for i := 0 to 500000 do 6 begin 7 Canvas.TextOut(10, 10, IntToStr(i)); 8 end; 9 end;

上面程序运行时, 在程序运行期间拖动窗体,窗体基本是 卡"死" 的。

解决卡死方法1(Application.ProcessMessages)

一个简单的办法( Application.ProcessMessages )来解决这个问题,代码如下:

1 procedure TForm1.btn2Click(Sender: TObject); 2 var 3 i: Integer; 4 begin 5 for i := 0 to 500000 do 6 begin 7 Canvas.TextOut(10, 10, IntToStr(i)); 8 Application.ProcessMessages; // 解决方法之一 9 end; 10 end;

这个 Application.ProcessMessages 它会检查并先处理消息队列中的其他消息.
但这算不上多线程, 运行中拖动窗体, 你会发现循环会暂停下来...

在 Delphi 中使用多线程有两种方法:

  1. 调用 API
  2. 使用 TThread 类
解决卡死方法2(调用 API)

1 function MyTest(p: Pointer): Integer; stdcall; 2 var 3 i: Integer; 4 begin 5 for i := 0 to 500000 do 6 begin 7 Form1.Canvas.Lock; // 在 Canvas 中 Lock ,其他访问先暂停 8 Form1.Canvas.TextOut(10, 10, IntToStr(i)); 9 Form1.Canvas.Unlock; // 用完了,解锁 10 end; 11 Result := 0; 12 end; 13 14 procedure TForm1.btn3Click(Sender: TObject); 15 var 16 ID: Cardinal; 17 begin 18 CreateThread(nil, 0, @MyTest, nil, 0, ID); 19 end;

CreateThread 要使用的函数是系统级的,不能是某个类的方法,必须有严格的格式(参数、返回值)要求,还必须用上 stdcall 是协调参数顺序的,虽然这里只有一个参数没有顺序可言,但这是使用系统函数的惯例。

CreateThread 还需要一个 var 参数来接收新建线程的 ID,在 Delphi 10.3.3 中为 Cardinal 类型。

解决卡死方法3(使用 TThread 类)

TThread 类有一个抽象方法(Execute),抽象类只能被继承使用,下面继承为 TMyThread,主要是实现抽象方法 Execute,等我们实例化 TMyThread 后,首先会执行 Execute 方法中的代码。

1 type 2 TMyThread = class(TThread) 3 protected 4 procedure Execute; override; 5 end; 6 7 implementation 8 9 {$R *.dfm} 10 { TMyThread } 11 12 procedure TMyThread.Execute; 13 var 14 i: Integer; 15 begin 16 inherited; 17 FreeOnTerminate := True; 18 for i := 0 to 500000 do 19 begin 20 Form1.Canvas.Lock; 21 Form1.Canvas.TextOut(10, 10, IntToStr(i)); 22 Form1.Canvas.Unlock; 23 end; 24 end; 25 26 procedure TForm1.btn1Click(Sender: TObject); 27 var 28 MyThread: TMyThread; 29 begin 30 MyThread := TMyThread.Create(True); 31 MyThread.Resume; 32 33 //TMyThread.Create(False); 也可以这样实例化 34 35 //with TMyThread.Create(True) do Resume; 还可以这样实例化 36 end;

在上面代码中,实例化用到的 MyThread 变量,毫无用处,可以直接

如何实现多线程编程的基础概念?

TMyThread.Create(False);

执行或者

with TMyThread.Create(True) do Resume;

线程建立后不会立即调用 Execute,可以在需要的时候用 Resume 方法执行线程。

在 TThread 类的例子中,还有一个这样的句子:

FreeOnTerminate := True;

由于 TThread 的特殊性,很多时候我们不能确定线程什么时候执行完毕,因此不能 Free,如果 FreeOnTerminate 为 True,线程执行完毕后自动释放。

本文共计937个文字,预计阅读时间需要4分钟。

如何实现多线程编程的基础概念?

编写一个循环程序,执行50000次,每次在程序界面的左上方(10,10)位置输出数字,代码如下:

pascalprocedure TForm1.btn2Click(Sender: TObject);var i: Integer;begin for i :=0 to 50000 do begin Writeln(10, 10, i); end;end;

先编写一个循环 50000 次的程序,每次在程序界面左上方(10,10)的位置输出数字,代码如下:

1 procedure TForm1.btn2Click(Sender: TObject); 2 var 3 i: Integer; 4 begin 5 for i := 0 to 500000 do 6 begin 7 Canvas.TextOut(10, 10, IntToStr(i)); 8 end; 9 end;

上面程序运行时, 在程序运行期间拖动窗体,窗体基本是 卡"死" 的。

解决卡死方法1(Application.ProcessMessages)

一个简单的办法( Application.ProcessMessages )来解决这个问题,代码如下:

1 procedure TForm1.btn2Click(Sender: TObject); 2 var 3 i: Integer; 4 begin 5 for i := 0 to 500000 do 6 begin 7 Canvas.TextOut(10, 10, IntToStr(i)); 8 Application.ProcessMessages; // 解决方法之一 9 end; 10 end;

这个 Application.ProcessMessages 它会检查并先处理消息队列中的其他消息.
但这算不上多线程, 运行中拖动窗体, 你会发现循环会暂停下来...

在 Delphi 中使用多线程有两种方法:

  1. 调用 API
  2. 使用 TThread 类
解决卡死方法2(调用 API)

1 function MyTest(p: Pointer): Integer; stdcall; 2 var 3 i: Integer; 4 begin 5 for i := 0 to 500000 do 6 begin 7 Form1.Canvas.Lock; // 在 Canvas 中 Lock ,其他访问先暂停 8 Form1.Canvas.TextOut(10, 10, IntToStr(i)); 9 Form1.Canvas.Unlock; // 用完了,解锁 10 end; 11 Result := 0; 12 end; 13 14 procedure TForm1.btn3Click(Sender: TObject); 15 var 16 ID: Cardinal; 17 begin 18 CreateThread(nil, 0, @MyTest, nil, 0, ID); 19 end;

CreateThread 要使用的函数是系统级的,不能是某个类的方法,必须有严格的格式(参数、返回值)要求,还必须用上 stdcall 是协调参数顺序的,虽然这里只有一个参数没有顺序可言,但这是使用系统函数的惯例。

CreateThread 还需要一个 var 参数来接收新建线程的 ID,在 Delphi 10.3.3 中为 Cardinal 类型。

解决卡死方法3(使用 TThread 类)

TThread 类有一个抽象方法(Execute),抽象类只能被继承使用,下面继承为 TMyThread,主要是实现抽象方法 Execute,等我们实例化 TMyThread 后,首先会执行 Execute 方法中的代码。

1 type 2 TMyThread = class(TThread) 3 protected 4 procedure Execute; override; 5 end; 6 7 implementation 8 9 {$R *.dfm} 10 { TMyThread } 11 12 procedure TMyThread.Execute; 13 var 14 i: Integer; 15 begin 16 inherited; 17 FreeOnTerminate := True; 18 for i := 0 to 500000 do 19 begin 20 Form1.Canvas.Lock; 21 Form1.Canvas.TextOut(10, 10, IntToStr(i)); 22 Form1.Canvas.Unlock; 23 end; 24 end; 25 26 procedure TForm1.btn1Click(Sender: TObject); 27 var 28 MyThread: TMyThread; 29 begin 30 MyThread := TMyThread.Create(True); 31 MyThread.Resume; 32 33 //TMyThread.Create(False); 也可以这样实例化 34 35 //with TMyThread.Create(True) do Resume; 还可以这样实例化 36 end;

在上面代码中,实例化用到的 MyThread 变量,毫无用处,可以直接

如何实现多线程编程的基础概念?

TMyThread.Create(False);

执行或者

with TMyThread.Create(True) do Resume;

线程建立后不会立即调用 Execute,可以在需要的时候用 Resume 方法执行线程。

在 TThread 类的例子中,还有一个这样的句子:

FreeOnTerminate := True;

由于 TThread 的特殊性,很多时候我们不能确定线程什么时候执行完毕,因此不能 Free,如果 FreeOnTerminate 为 True,线程执行完毕后自动释放。