教
教父
Unregistered / Unconfirmed
GUEST, unregistred user!
我们知道,大部分的VCL是线程不安全的,所以在用线程操作VCL的时候必须要用到Synchronize。
我们再来看看Synchronize是个什么东西。
《Delphi4编程技术内幕》的P126中说:“具体来说,Synchronize做一些控制工作,使你的线
程临时成为应用程序主线程的一部分。在这个进程中,你可以访问VCL。当不再需要VCL的时候,
你应当为断代码中的同步部分。于是你的程序将再次具有多个线程。”
言下之意,当某个线程访问VCL的时候,所有的其它线程都停止下来了,我想这是因为其它的
线程要等待访问VCL。
《Delphi4开发大全(上)》的P427中揭示了Synchronize的奥秘:“当您创建一个线程对象时,
VCL会创建和维护一个隐含的线程窗口。这个窗口的作用是把通过Synchronize()调用的方法
排队。Synchronize把通过Method参数传递过来的方法保存在TThread的FMethod字段中,然后
把一个CM_EXECPROC消息发给线程窗口,并且把消息的lParam参数设为Self(这里就是线程对
象)。当线程窗口的窗口程序收到这个消息,它就调用FMethod字段所指定的方法。由于线程
窗口是在主线程内创建的,线程窗口的窗口过程也被主线程执行。因此,FMethod字段所指定
的方法就在主线程内执行。”
《C++Builder5开发人员指南》中同样有类似的描述:“Synchronize方法等待主VCL线程进入
消息循环,然后执行传入的方法。”
从上面引述的观点来看,我们可以清楚地知道如果一个线程要操作VCL,它就必须得停下来,
等待其它的线程让出VCL,这样,线程的效率自然就降低了。
在《Delphi4开发大全》中也提到了可以通过消息来进行线程的同步,于是我编写了如下的代
码。
//下面是线程单元
unit Unit2;
interface
uses
SysUtils,Classes,Unit1,Windows;
type
TMsgThread = class(TThread)
private
{ Private declarations }
FStr:String;
procedure ShowInMemo;
protected
procedure Execute;
override;
public
Num:Integer;
end;
implementation
{$DEFINE USE_MSG} //这一句决定是采用消息还是采用Synchronize。
procedure TMsgThread.Execute;
begin
while not Terminateddo
begin
FStr:='第'+IntToStr(Num)+'行:'+IntToStr(GetTickCount);
{$IFDEF USE_MSG}
PostMessage(Form1.Handle,WM_MSG,Num,Integer(@FStr[1]));
{$else
}
Synchronize(ShowInMemo);
{$ENDIF}
end;
end;
procedure TMsgThread.ShowInMemo;
begin
Form1.Memo1.Lines.Strings[Num-1]:=FStr;
end;
end.
//以下是主程序
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
const
WM_MSG=WM_USER+1;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
protected
procedure WMMsg(var Msg:TMessage);message WM_MSG;
end;
var
Form1: TForm1;
implementation
uses Unit2;
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
for i:=1 to 10do
begin
Memo1.Lines.Add('');
with TMsgThread.Create(True)do
begin
Num:=i;
Resume;
end;
end;
end;
procedure TForm1.WMMsg(var Msg: TMessage);
var
i:integer;
s:String;
begin
i:=Msg.wParam;
s:=String(Pointer(Msg.LParam));
Memo1.Lines.Strings[i-1]:=s;
end;
end.
这个程序其实很简单,建立一些线程,同时操作Memo1,在其中显示字符串。
当在Unit2中定义了USE_MSG时,程序将使用自定义的WM_MSG消息的方式来同步线程,否则所用
Synchronize。
在Unit1中,每当收到WM_MSG时根据MSG的信息来决定写入Memo1的位置和字符串。
两种方式都能正常的工作,但是,我想知道的是:两者的效率孰高孰低?
个人认为,采用消息的方式,线程不用停下来等待VCL的操作权,如果这个线程是个计算
密集型的,这样做无疑会大大提高效率。
当然,对于VCL的访问,此处仍然是逐一处理的。
请各位高手发表看法,谢谢!
我们再来看看Synchronize是个什么东西。
《Delphi4编程技术内幕》的P126中说:“具体来说,Synchronize做一些控制工作,使你的线
程临时成为应用程序主线程的一部分。在这个进程中,你可以访问VCL。当不再需要VCL的时候,
你应当为断代码中的同步部分。于是你的程序将再次具有多个线程。”
言下之意,当某个线程访问VCL的时候,所有的其它线程都停止下来了,我想这是因为其它的
线程要等待访问VCL。
《Delphi4开发大全(上)》的P427中揭示了Synchronize的奥秘:“当您创建一个线程对象时,
VCL会创建和维护一个隐含的线程窗口。这个窗口的作用是把通过Synchronize()调用的方法
排队。Synchronize把通过Method参数传递过来的方法保存在TThread的FMethod字段中,然后
把一个CM_EXECPROC消息发给线程窗口,并且把消息的lParam参数设为Self(这里就是线程对
象)。当线程窗口的窗口程序收到这个消息,它就调用FMethod字段所指定的方法。由于线程
窗口是在主线程内创建的,线程窗口的窗口过程也被主线程执行。因此,FMethod字段所指定
的方法就在主线程内执行。”
《C++Builder5开发人员指南》中同样有类似的描述:“Synchronize方法等待主VCL线程进入
消息循环,然后执行传入的方法。”
从上面引述的观点来看,我们可以清楚地知道如果一个线程要操作VCL,它就必须得停下来,
等待其它的线程让出VCL,这样,线程的效率自然就降低了。
在《Delphi4开发大全》中也提到了可以通过消息来进行线程的同步,于是我编写了如下的代
码。
//下面是线程单元
unit Unit2;
interface
uses
SysUtils,Classes,Unit1,Windows;
type
TMsgThread = class(TThread)
private
{ Private declarations }
FStr:String;
procedure ShowInMemo;
protected
procedure Execute;
override;
public
Num:Integer;
end;
implementation
{$DEFINE USE_MSG} //这一句决定是采用消息还是采用Synchronize。
procedure TMsgThread.Execute;
begin
while not Terminateddo
begin
FStr:='第'+IntToStr(Num)+'行:'+IntToStr(GetTickCount);
{$IFDEF USE_MSG}
PostMessage(Form1.Handle,WM_MSG,Num,Integer(@FStr[1]));
{$else
}
Synchronize(ShowInMemo);
{$ENDIF}
end;
end;
procedure TMsgThread.ShowInMemo;
begin
Form1.Memo1.Lines.Strings[Num-1]:=FStr;
end;
end.
//以下是主程序
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
const
WM_MSG=WM_USER+1;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
protected
procedure WMMsg(var Msg:TMessage);message WM_MSG;
end;
var
Form1: TForm1;
implementation
uses Unit2;
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
for i:=1 to 10do
begin
Memo1.Lines.Add('');
with TMsgThread.Create(True)do
begin
Num:=i;
Resume;
end;
end;
end;
procedure TForm1.WMMsg(var Msg: TMessage);
var
i:integer;
s:String;
begin
i:=Msg.wParam;
s:=String(Pointer(Msg.LParam));
Memo1.Lines.Strings[i-1]:=s;
end;
end.
这个程序其实很简单,建立一些线程,同时操作Memo1,在其中显示字符串。
当在Unit2中定义了USE_MSG时,程序将使用自定义的WM_MSG消息的方式来同步线程,否则所用
Synchronize。
在Unit1中,每当收到WM_MSG时根据MSG的信息来决定写入Memo1的位置和字符串。
两种方式都能正常的工作,但是,我想知道的是:两者的效率孰高孰低?
个人认为,采用消息的方式,线程不用停下来等待VCL的操作权,如果这个线程是个计算
密集型的,这样做无疑会大大提高效率。
当然,对于VCL的访问,此处仍然是逐一处理的。
请各位高手发表看法,谢谢!