您的位置:首页 > 编程语言 > Delphi

Delphi多线程编程之四 线程安全和VCL

2011-10-05 13:45 183 查看
◆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源程序,发现也是调用临界区,这个太不方便了,还是使用临界区好)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: