线程的一个例子,怎么不行呀,请教:只是简单低创建一个线程对象,然后用它来刷新佛form1的caption,但是运行的时候,CPU还是使用了100%,怎么回事压?请指教,多谢!!线程:
unit Unit2;interfaceuses
Classes,SysUtils;type
TTestThread = class(TThread)
private
{ Private declarations }
FI: Integer;
protected
procedure Execute; override;
procedure AddNum;
procedure OutAddNum;
end;implementationUses
Unit1;{ Important: Methods and properties of objects in VCL or CLX can only be used
in a method called using Synchronize, for example, Synchronize(UpdateCaption); and UpdateCaption could look like, procedure TTestThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }{ TTestThread }procedure TTestThread.AddNum;
var
i: integer;
j: Double;
begin
for i := 0 to FI do
begin
j := Sqrt(i);
Form1.Caption := FloatToStr(j);
end;
end;procedure TTestThread.Execute;
begin
{ Place thread code here }
OutAddNum;
end;procedure TTestThread.OutAddNum;
begin
Self.FI := 100000;
Synchronize(AddNum);
end;end.
调用:
procedure TForm1.Button1Click(Sender: TObject);
var
tt: TTestThread;
begin
With TTestThread.Create(False) do
begin
end;
end;
为何CPU用了100,该怎么处理?多谢!!!
unit Unit2;interfaceuses
Classes,SysUtils;type
TTestThread = class(TThread)
private
{ Private declarations }
FI: Integer;
protected
procedure Execute; override;
procedure AddNum;
procedure OutAddNum;
end;implementationUses
Unit1;{ Important: Methods and properties of objects in VCL or CLX can only be used
in a method called using Synchronize, for example, Synchronize(UpdateCaption); and UpdateCaption could look like, procedure TTestThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }{ TTestThread }procedure TTestThread.AddNum;
var
i: integer;
j: Double;
begin
for i := 0 to FI do
begin
j := Sqrt(i);
Form1.Caption := FloatToStr(j);
end;
end;procedure TTestThread.Execute;
begin
{ Place thread code here }
OutAddNum;
end;procedure TTestThread.OutAddNum;
begin
Self.FI := 100000;
Synchronize(AddNum);
end;end.
调用:
procedure TForm1.Button1Click(Sender: TObject);
var
tt: TTestThread;
begin
With TTestThread.Create(False) do
begin
end;
end;
为何CPU用了100,该怎么处理?多谢!!!
var
tt: TTestThread;
begin
With TTestThread.Create(False) do
begin
freeonterminate:=true
end;
end;
var
tt: TTestThread;
begin
With TTestThread.Create(true) do
begin
freeonterminate:=true;
resume;
end;
end;
实现这两个方法!
不要直接访问主线成中的VCL...你在 TTestThread.AddNum;直接访问了。
在线程内部设一个TForm变量,传递近来.好好看看DEMO 里和 HELP 目录下的线程例子..
interface
uses
Classes,SysUtils,messages,windows;
Const
My_Msg=WM_User+100;
type
TTestThread = class(TThread)
private
myhandle:Thandle;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean;handle:Thandle);
end;implementationconstructor TTestThread.Create(CreateSuspended: Boolean; handle:Thandle);
begin
inherited create(CreateSuspended);
myhandle:=handle;
end;procedure TTestThread.Execute;
var
i: integer;
begin
for i := 0 to 10000 do
begin
postmessage(myhandle,MY_MSG,1,i);
sleep(100);
end;
end;
end.<hr>unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,unit2;type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
procedure getmsg(var msg:Tmessage);message MY_Msg;
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
TTestThread.Create(False,handle);
end;procedure TForm1.getmsg(var msg: Tmessage);
begin
if msg.Msg=MY_msg then
if msg.WParam =1 then
form1.Caption :=floattostr(Sqrt(msg.LParam)) ;
end;end.
<hr>
这样就可以了!
需要吗?为什么?另外,我是没有直接访问Vcl的,
我是procedure TTestThread.OutAddNum;
begin
Self.FI := 100000;
Synchronize(AddNum);
end;
有什么问题吗?能否详细讲一下,多谢!!
Form1.Caption := FloatToStr(j) + '-' + Form1.Caption;
procedure TTestThread.Execute;
begin
Synchronize(OutAddNum);
end;
*******************************问题的标题是: 在线程中,Synchronize和用消息处理哪个效率高? (200分 )
来自:教父 时间:2001-12-3 16:15:00 ID:760828 我们知道,大部分的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;interfaceuses
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 Terminated do
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;interfaceuses
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;implementationuses Unit2;{$R *.DFM}procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
for i:=1 to 10 do
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的访问,此处仍然是逐一处理的。
var
j: Double;
begin
j := Sqrt(FI);
Form1.Caption := FloatToStr(j);
end;procedure TTestThread.Execute;
begin
{ Place thread code here }
OutAddNum;
end;procedure TTestThread.OutAddNum;
begin
FI := 0;
while (not Terminated) and (FI < 100000) do
begin
Synchronize(AddNum);
Inc(FI);
end;
end;//以上代码我未测试过
我上面所用的方法就是与 hthunter(核桃-我的心在下雨,雨中我和她携手漫步) 所讲的一样,怎么会不行,我都测试过的!try ~~
多谢!我还是没有十分理解Synchronize的用法,
并且,大哥给的代码只能在程序运行的时候,拖动一下(!!!)
窗口,而后,又是不能动了,怎么回事??
to wnhoo(e梦缘) :
那句话不是说你的,请别介意。因为我看到
用消息的方式来同步好像不太好(为什么??我也不太清楚),
所以,你的那段代码我还没有试,不好意思。:)
至于同步影响不是很大的,你可以调动sleep(100);到合适大小!我想我上面方法即使不是最好的,也不会有比上面更好的方法了,或许上面处理真的会有点影响你说的同步;具体看你用在什么方面了!
关键是封装进取后,某个控件的事件触发如何传入到这个线程里?我现在使用Indy里的IdUdpClient/Server监控车间里的各台计算机的信息,
怎么把被控端的捕捉屏幕画面封装到一个线程里面传到主控端?主控端又该如何封装他触发的Read事件到线程里? 多谢!!
http://expert.csdn.net/expert/ltzz.shtm
sleep(sleep(0)就够了)交还CPU控制权;
sqrt一个double实在占不了多少资源;
如果在execute里一直执著地运行代码,100%的占用率是难免的。
后来问题倒是解决了,但是不知所以然。
我觉得你应该把循环移到线程里,循环条件为while not terminated do