线程的一个例子,怎么不行呀,请教:只是简单低创建一个线程对象,然后用它来刷新佛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,该怎么处理?多谢!!!

解决方案 »

  1.   

    procedure TForm1.Button1Click(Sender: TObject);
    var
      tt: TTestThread;
    begin
      With TTestThread.Create(False) do
      begin
        freeonterminate:=true
      end;
    end;
      

  2.   

    procedure TForm1.Button1Click(Sender: TObject);
    var
      tt: TTestThread;
    begin
      With TTestThread.Create(true) do
      begin
        freeonterminate:=true;
        resume;
      end;
    end;
      

  3.   

    你构造和析构在那里??????????
    实现这两个方法!
    不要直接访问主线成中的VCL...你在 TTestThread.AddNum;直接访问了。
    在线程内部设一个TForm变量,传递近来.好好看看DEMO 里和 HELP 目录下的线程例子..
      

  4.   

    unit Unit2;
    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>
    这样就可以了!
      

  5.   

    没有实现自己的构造(析构)函数,
    需要吗?为什么?另外,我是没有直接访问Vcl的,
    我是procedure TTestThread.OutAddNum;
    begin
      Self.FI := 100000;
      Synchronize(AddNum);
    end;
    有什么问题吗?能否详细讲一下,多谢!!
      

  6.   


    Form1.Caption := FloatToStr(j) + '-' + Form1.Caption;
    procedure TTestThread.Execute;
    begin
      Synchronize(OutAddNum);
    end;
      

  7.   

    转帖
    *******************************问题的标题是: 在线程中,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的访问,此处仍然是逐一处理的。
      

  8.   

    楼主还没有搞清楚Synchronize的真正意义,实际上进入AddNum之后,不管你有没有用到Synchronize,cpu都会在执行完for循环后再把时间交给其他的线程。应该改成这样:procedure TTestThread.AddNum;
    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;//以上代码我未测试过
      

  9.   

    to  catch2008() 
    我上面所用的方法就是与 hthunter(核桃-我的心在下雨,雨中我和她携手漫步) 所讲的一样,怎么会不行,我都测试过的!try ~~
      

  10.   

    to  hthunter(核桃-我的心在下雨,雨中我和她携手漫步) :
      多谢!我还是没有十分理解Synchronize的用法,
    并且,大哥给的代码只能在程序运行的时候,拖动一下(!!!)
    窗口,而后,又是不能动了,怎么回事??
    to wnhoo(e梦缘)  :
      那句话不是说你的,请别介意。因为我看到
    用消息的方式来同步好像不太好(为什么??我也不太清楚),
    所以,你的那段代码我还没有试,不好意思。:)
      

  11.   

    我想对于你这种想法,只有通过消息,并且循环的放在execute中处理!这样才能使得线程发挥作用,按您上面的所写,与没用线程效果一样的;
    至于同步影响不是很大的,你可以调动sleep(100);到合适大小!我想我上面方法即使不是最好的,也不会有比上面更好的方法了,或许上面处理真的会有点影响你说的同步;具体看你用在什么方面了!
      

  12.   

    在线程使用一个public的变量,控件触发时候改动这个值来做除相应的动作
      

  13.   

    我认为是你在AddNum中使用了双精度变量的原因,而且用了Sqrt,浮点运算非常耗资源!!
      

  14.   

    如果是一个事件里的操作是一个耗时操作,怎么把它封装进一个线程里?
    关键是封装进取后,某个控件的事件触发如何传入到这个线程里?我现在使用Indy里的IdUdpClient/Server监控车间里的各台计算机的信息,
    怎么把被控端的捕捉屏幕画面封装到一个线程里面传到主控端?主控端又该如何封装他触发的Read事件到线程里? 多谢!!
      

  15.   

    先生,您的脱题了!CSDN论坛的 用户行为准则
    http://expert.csdn.net/expert/ltzz.shtm
      

  16.   

    CPU占用率:
    sleep(sleep(0)就够了)交还CPU控制权;
    sqrt一个double实在占不了多少资源;
    如果在execute里一直执著地运行代码,100%的占用率是难免的。
      

  17.   

    我也曾经遇见过这种情况,也问过很多人,但是答案还是不太满意。
    后来问题倒是解决了,但是不知所以然。
    我觉得你应该把循环移到线程里,循环条件为while not terminated do