- ◆Delphi多线程编程之四 线程安全和VCL ◆(乌龙哈里2008-10-12)
- (调试环境:Delphi2007+WinXPsp3 例程:Tst_Thread4.dpr)
- 由于Delphi VCL在设计成大部分在主线程访问,因而,当多个线程同时访问VCL时,就非安全。
- 其实线程的安全性如上面那个读全局变量来说,那个全局变量是非线程安全的,因为当另外一个线程访问它的时候,它的数值还在被前一个线程改动中。这在非线程安全的对象中就会造成很严重的后果,比如一个对象的创立时的初始值被另一个线程改变了,后果相当地严重。
- VCL中,连很基础的Tlist都是非线程安全,要多个线程操纵List时,用TThreadList来替代。
- unit Tst_Thread4U;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls;
- type
- TForm1 = class(TForm)
- Button1: TButton;
- Memo1: TMemo;
- procedure Button1Click(Sender: TObject);
- procedure Button2Click(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
-
- TMyThread=class(TThread)
- protected
- procedure Execute;override;
- procedure ShowInMemo;
- end;
- var
- Form1: TForm1;
-
- implementation
-
- {$R *.dfm}
- const
- MaxSize=1000;
- var
- NextNumber:Integer=0;
- GlobalNum:Integer;
-
- function GetNextNumber:Integer;
- begin
- Result:=NextNumber;
- inc(NextNumber);
- end;
-
- { TMyThread }
-
- procedure TMyThread.Execute;
- var
- i:Integer;
- begin
- FreeOnTerminate:=True; //终止后自动free
- for i := 1 to MaxSize do
- begin
- GlobalNum:=GetNextNumber;
- Sleep(5);
- Synchronize(ShowInMemo);
- // ShowInMemo;
- end;
- end;
-
- procedure TMyThread.ShowInMemo;
- begin
- Form1.Memo1.Lines.Add(inttostr(GlobalNum));
- end;
-
- procedure TForm1.Button1Click(Sender: TObject);
- begin
- TMyThread.Create(False);
- TMyThread.Create(False);
- end;
-
- end.
-
- 上面这个例程,把输出到Memo1放在线程里了,所以要在Execute()内用到Synchronize()函数,这样才是线程安全。
-
- 一、Synchronize()函数。
- 是个重载函数,有两种引用形式:
- class procedure Synchronize(AThread: TThread; AMethod: TThreadMethod); overload;
- procedure Synchronize(AMethod: TThreadMethod); overload;
- Amethod是线程的一个自定义不带参数过程(!!太烦了,不能带参数,好不方便)。
- Synchronize()调用了Windows的SendMessage()向主线程发一消息。主线程必须已建立消息队列,并且不断地从消息队类中检索消息。一旦主线程检索到消息,就执行Synchronize()所指定的代码。(ps:我查了Vcl源程序,发现也是调用临界区,这个太不方便了,还是使用临界区好)。
|
请发表评论