在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
本例效果图: 新建应用程序(先来个单线程),添加一个Button按钮,编辑代码如下: procedure TForm1.Button1Click(Sender: TObject); var i: Integer; begin for i := 0 to 500000 do begin Canvas.TextOut(60, 45, IntToStr(i)); {在绘图表面显示数字(i)} end; end; OK,运行看看,程序怎么好像是'死'的?点击按钮“开始”后,程序在绘图表面坐标(60,45)处开始显示数字,但我移动窗口却根本没有反映,一直到for语句结束才处理窗口移动的操作。这样不行,一个应用程序怎能如此“死板”呢,这种情况下,Delphi 为我们提供了一个简单的解决办法(Application.ProcessMessages),改进代码如下(还是单线程): procedure TForm1.Button1Click(Sender: TObject); var i: Integer; begin for i := 0 to 500000 do begin Canvas.TextOut(60, 45, IntToStr(i)); Application.ProcessMessages; {检查并优先处理消息队列中的消息,应用于比较费时的循环} end; end; 再次运行,问题解决,但又略有不足,如下图所示,
可以看到当我们移动窗口时,计数竟然暂停了。那如果我不想计数暂停而又希望计数的过程中能够移动窗口呢?OK,操作系统为我们提供了更强大的多线程API来解决这种问题,那么什么是多线程呢? 多线程概述 进程和线程都是操作系统的概念。进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭。 好了,概念性的东西我们尽量少讲,下面就开始我们的多线程编程吧^_^,不过,在使用多线程以前, 让我们先简单修改一下程序(将执行代码封装为一个函数): function MyFun: Integer; var i: Integer; begin for i := 0 to 500000 do begin Form1.Canvas.Lock; Form1.Canvas.TextOut(10, 10, IntToStr(i)); Form1.Canvas.Unlock; end; Result := 0; end; procedure TForm1.Button1Click(Sender: TObject); begin MyFun; end; 细数上面程序的变化: function MyFun(p: Pointer): Integer; stdcall; var i: Integer; begin for i := 0 to 500000 do begin Form1.Canvas.Lock; Form1.Canvas.TextOut(10, 10, IntToStr(i)); Form1.Canvas.Unlock; end; Result := 0; end; procedure TForm1.Button1Click(Sender: TObject); var ID: THandle; begin CreateThread(nil, 0, @MyFun, nil, 0, ID); end;
代码分析: type TMyThread = class(TThread) protected procedure Execute; override; end; procedure TMyThread.Execute; var i: Integer; begin FreeOnTerminate := True; {这可以让线程执行完毕后随即释放} for i := 0 to 500000 do begin Form1.Canvas.Lock; Form1.Canvas.TextOut(10, 10, IntToStr(i)); Form1.Canvas.Unlock; end; end; procedure TForm1.Button1Click(Sender: TObject); begin TMyThread.Create(False); end;
TThread 类有一个抽象方法(Execute), 因而是个抽象类, 抽象类只能继承使用, 上面是继承为 TMyThread.继承 TThread 主要就是实现抽象方法 Execute(把我们的代码写在里面), 等我们的 TMyThread 实例化后, 首先就会执行 Execute 方法中的代码.按常规我们一般这样去实例化: procedure TForm1.Button1Click(Sender: TObject); var MyThread: TMyThread; begin MyThread := TMyThread.Create(False); end;
因为 MyThread 变量在这里毫无用处(并且编译器还有提示), 所以不如直接写做 TMyThread.Create(False); 我们还可以轻松解决一个问题, 如果: TMyThread.Create(True) ? procedure TForm1.Button1Click(Sender: TObject); var MyThread: TMyThread; begin MyThread := TMyThread.Create(True); MyThread.Resume; end; //可简化为: procedure TForm1.Button1Click(Sender: TObject); begin with TMyThread.Create(True) do Resume; end; |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论