delphi线程详细教程简单到复杂(4)

2019-03-03 23:03

Lock;

TextOut(pt2.X, pt2.Y, IntToStr(i)); Unlock; end; end; Result := 0; end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var

ID: DWORD; begin

pt := Point(X, Y);

CreateThread(nil, 0, @MyThreadFun, @pt, 0, ID);

{下面这种写法更好理解, 其实不必, 因为 PPoint 会自动转换为 Pointer 的}

//CreateThread(nil, 0, @MyThreadFun, Pointer(@pt), 0, ID); end; end.

这个例子还有不严谨的地方: 当一个线程 Lock 窗体的 Canvas 时, 其他线程在等待; 线程在等待时, 其中的计数也还在增加. 这也就是说: 现在并没有去处理线程的同步; 同步是多线程中最重要的课题, 快到了.

另外有个小技巧: 线程函数的参数是个 32 位(4个字节)的指针, 仅就本例来讲, 可以让它的 \高16位\和 \低16位\分别携带 X 和 Y; 这样就不需要哪个全局的 pt 变量了.

其实在 Windows 的消息中就是这样传递坐标的, 在 Windows 的消息中一般高字节是 Y、低字节是 X; 咱们这么来吧, 这样还可以使用给消息准备的一些方便的函数.

重写本例代码(当然运行效果和窗体文件都是一样的):

unit Unit1;

interface uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs; type

TForm1 = class(TForm)

procedure FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); end; var

Form1: TForm1;

implementation

{$R *.dfm}

function MyThreadFun(p: Pointer): Integer; stdcall; var

i: Integer; x,y: Word; begin

x := LoWord(Integer(p)); y := HiWord(Integer(p));

{如果不使用 LoWord、HiWord 函数可以像下面这样: } //x := Integer(p); //y := Integer(p) shr 16; for i := 0 to 1000000 do begin

with Form1.Canvas do begin Lock;

TextOut(x, y, IntToStr(i)); Unlock; end; end; Result := 0; end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var

ID: DWORD; num: Integer; begin

num := MakeLong(X, Y);

{如果不使用 MekeLong、MakeWParam、MakeLParam、MakeResult 等函数, 可以像下面这样: }

//num := Y shl 16 + X;

CreateThread(nil, 0, @MyThreadFun, Ptr(num), 0, ID);

{上面的 Ptr 是专门将一个数字转换为指针的函数, 当然也可以这样: } //CreateThread(nil, 0, @MyThreadFun, Pointer(num), 0, ID); end; end.

㈣、入口函数的指针

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


delphi线程详细教程简单到复杂(4).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:51单片机使用ds3231模块

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: