第一范文网 - 专业文章范例文档资料分享平台

delphi线程详细教程简单到复杂

来源:用户分享 时间:2025/5/23 18:50:30 本文由loading 分享 下载这篇文档手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xxxxxxx或QQ:xxxxxx 处理(尽可能给您提供完整文档),感谢您的支持与谅解。

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) ?

这样线程建立后就不会立即调用 Execute, 可以在需要的时候再用 Resume 方法执行线程, 譬如:

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;

一、入门 ㈠、

function CreateThread(

lpThreadAttributes: Pointer; {安全设置} dwStackSize: DWORD; {堆栈大小}

lpStartAddress: TFNThreadStartRoutine; {入口函数} lpParameter: Pointer; {函数参数} dwCreationFlags: DWORD; {启动选项} var lpThreadId: DWORD {输出线程 ID } ): THandle; stdcall; {返回线程句柄}

在 Windows 上建立一个线程, 离不开 CreateThread 函数;

TThread.Create 就是先调用了 BeginThread (Delphi 自定义的), BeginThread 又调用的 CreateThread.

既然有建立, 就该有释放, CreateThread 对应的释放函数是: ExitThread, 譬如下面代码:

procedure TForm1.Button1Click(Sender: TObject); begin

ExitThread(0); {此句即可退出当前程序, 但不建议这样使用} end;

代码注释:

当前程序是一个进程, 进程只是一个工作环境, 线程是工作者;

每个进程都会有一个启动线程(或叫主线程), 也就是说: 我们之前大量的编码都是写给这个主线程的; 上面的 ExitThread(0); 就是退出这个主线程;

系统不允许一个没有线程的进程存在, 所以程序就退出了.

另外: ExitThread 函数的参数是一个退出码, 这个退出码是给之后的其他函数用的, 这里随便给个无符号整数即可.

或许你会说: 这个 ExitThread 挺好用的; 其实不管是用 API 还是用 TThread 类写多线程, 我们很少用到它; 因为:

1、假如直接使用 API 的 CreateThread, 它执行完入口函数后会自动退出, 无需 ExitThread; 2、用 TThread 类建立的线程又绝不能使用 ExitThread 退出; 因为使用 TThread 建立线程时会同时分配更多资源(譬如你自定义的成员、还有它的祖先类(TObject)分配的资源等等), 如果用 ExitThread

给草草退出了, 这些资源将得不到释放而导致内存泄露. 尽管 Delphi 提供了 EndThread(其内部调用 ExitThread), 这也不需要我们手动操作(假如非要手动操作也是件很麻烦的事情, 因为很多时候你不知道线程是什么时候执行完毕的).

除了 CreateThread, 还有一个 CreateRemoteThread, 可在其他进程中建立线程, 这不应该是现在学习的重点;

现在先集中精力把 CreateThread 的参数搞彻底.

倒着来吧, 先谈谈 CreateThread 将要返回的 \线程句柄\

\句柄\类似指针, 但通过指针可读写对象, 通过句柄只是使用对象;

有句柄的对象一般都是系统级别的对象(或叫内核对象); 之所以给我们的是句柄而不是指针, 目的只有一个: \安全\

貌似通过句柄能做很多事情, 但一般把句柄提交到某个函数(一般是系统函数)后, 我们也就到此为止很难了解更多了; 事实上是系统并不相信我们.

不管是指针还是句柄, 都不过是内存中的一小块数据(一般用结构描述), 微软并没有公开句柄的结构细节, 猜一下它应该包括: 真实的指针地址、访问权限设置、引用计数等等.

既然 CreateThread 可以返回一个句柄, 说明线程属于 \内核对象\

实际上不管线程属于哪个进程, 它们在系统的怀抱中是平等的; 在优先级(后面详谈)相同的情况下, 系统会在相同的时间间隔内来运行一下每个线程, 不过这个间隔很小很小, 以至于让我们误以为程序是在不间断地运行.

这时你应该有一个疑问: 系统在去执行其他线程的时候, 是怎么记住前一个线程的数据状态的?

有这样一个结构 TContext, 它基本上是一个 CPU 寄存器的集合, 线程是数据就是通过这个结构切换的, 我们也可以通过 GetThreadContext 函数读取寄存器看看.

附上这个结构 TContext(或叫: CONTEXT、_CONTEXT) 的定义:

搜索更多关于: delphi线程详细教程简单到复杂 的文档
delphi线程详细教程简单到复杂.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.diyifanwen.net/c3wuac9y79e6ksx798r5h_2.html(转载请注明文章来源)
热门推荐
Copyright © 2012-2023 第一范文网 版权所有 免责声明 | 联系我们
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:xxxxxx 邮箱:xxxxxx@qq.com
渝ICP备2023013149号
Top