function CreateThread( lpThreadAttributes: Pointer; dwStackSize: DWORD; lpStartAddress: TFNThreadStartRoutine; {入口函数的指针} lpParameter: Pointer; dwCreationFlags: DWORD; var lpThreadId: DWORD ): THandle; stdcall;
到了入口函数了, 学到这个地方, 我查了一个入口函数的标准定义, 这个函数的标准返回值应该是 DWORD, 不过这函数在 Delphi 的 System 单元定义的是: TThreadFunc = function(Parameter: Pointer): Integer; 我以后会尽量使用 DWORD 做入口函数的返回值.
这个返回值有什么用呢?
等线程退出后, 我们用 GetExitCodeThread 函数获取的退出码就是这个返回值!
如果线程没有退出, GetExitCodeThread 获取的退出码将是一个常量 STILL_ACTIVE (259); 这样我们就可以通过退出码来判断线程是否已退出.
还有一个问题: 前面也提到过, 线程函数不能是某个类的方法! 假如我们非要线程去执行类中的一个方法能否实现呢?
尽管可以用 Addr(类名.方法名) 或 MethodAddress('published 区的方法名') 获取类中方法的地址, 但都不能当做线程的入口函数, 原因可能是因为类中的方法的地址是在实例化为对象时动态分配的.
后来换了个思路, 其实很简单: 在线程函数中再调用方法不就得了, 估计 TThread 也应该是这样.
下面的例子就尝试了用线程调用 TForm1 类中的方法, 并测试了退出码的相关问题.
本例效果图:

代码文件:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private procedure FormProc; {准备给线程使用的方法} end; var Form1: TForm1; implementation {$R *.dfm} var hThread: THandle; {线程入口函数} function MyThreadFun(p: Pointer): DWORD; stdcall; begin Form1.FormProc; {调用 TForm1 类的方法} Result := 99; {这个返回值将成为线程的退出代码, 99 是我随意给的数字} end; {TForm1 的方法, 本例中是给线程的入口函数调用的} procedure TForm1.FormProc; var i: Integer; begin for i := 0 to 200000 do begin with Form1.Canvas do begin Lock; TextOut(10, 10, IntToStr(i)); Unlock; end; end; end; {建立并执行线程} procedure TForm1.Button1Click(Sender: TObject); var ID: DWORD; begin hThread := CreateThread(nil, 0, @MyThreadFun, nil, 0, ID); end; {获取线程的退出代码, 并判断线程是否退出} procedure TForm1.Button2Click(Sender: TObject); var ExitCode: DWORD; begin GetExitCodeThread(hThread, ExitCode); if hThread = 0 then begin Text := '线程还未启动'; Exit; end; if ExitCode = STILL_ACTIVE then Text := Format('线程退出代码是: %d, 表示线程还未退出', [ExitCode]) else Text := Format('线程已退出, 退出代码是: %d', [ExitCode]); end; end.
窗体文件:
object Form1: TForm1 Left = 0 Top = 0 Caption = 'Form1' ClientHeight = 84 ClientWidth = 376 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13 object Button1: TButton Left = 183 Top = 32 Width = 75 Height = 25 Caption = 'Button1' TabOrder = 0 OnClick = Button1Click end object Button2: TButton Left = 280 Top = 32 Width = 75 Height = 25 Caption = 'Button2' TabOrder = 1 OnClick = Button2Click end end
分类:
Delphi 与 多线程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
2008-02-11 WinAPI: GetCurrentPositionEx - 获取当前的画笔位置
2008-02-11 WinAPI: GetLogicalDriveStrings - 获取系统中存在的逻辑驱动器字符串
2008-02-11 StrCopy、StrCat、StrPas
2008-02-11 WinAPI: GetLogicalDrives - 判断系统中存在的逻辑驱动器
2008-02-11 WinAPI: GetVolumeInformation - 读取文件系统信息
2008-02-11 WinAPI: GetDriveType - 获取磁盘类型
2008-02-11 WinAPI: GetDiskFreeSpaceEx - 获取磁盘容量信息