这个例子还有不严谨的地方: 当一个线程 Lock 窗体的 Canvas 时, 其他线程在等待; 线程在等待时, 其中的计数也还在增加. 这也就是说: 现在并没有去处理线程的同步; 同步是多线程中最重要的课题, 快到了.
另外有个小技巧: 线程函数的参数是个 32 位(4个字节)的指针, 仅就本例来讲, 可以让它的 "高16位" 和 "低16位" 分别携带 X 和 Y; 这样就不需要哪个全局的 pt 变量了.
其实在 Windows 的消息中就是这样传递坐标的, 在 Windows 的消息中一般高字节是 Y、低字节是 X; 咱们这么来吧, 这样还可以使用给消息准备的一些方便的函数.
重写本例代码(当然运行效果和窗体文件都是一样的):
unit Unit1; intece 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.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-25504-8.html
你想成为第几个死的
看上去听上去是有道理
让侵略者知道中国人不是懦夫