简单多线程如下:
unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;  TClientDataThread = class(TThread)
  private
  public
    TargetList :TStrings;
    str:string;
    procedure Execute; override;
  end;var
  Form1: TForm1;implementation{$R *.dfm}procedure TClientDataThread.Execute;
begin
  targetlist.Add('hello');
  str:='hello';
end;procedure TForm1.Button1Click(Sender: TObject);
var
  DataThread:TClientDataThread;
begin
  DataThread:=TClientDataThread.Create(true);
  DataThread.TargetList:=memo1.Lines;
  datathread.str:=button1.Caption;//为什么button1.caption不会变?
  DataThread.Resume;
end;end.我想问,既然memo1.lines会增加,为什么button1.caption不会变。这里我省略了结束线程等,就不要讨论了,我们只讨论第一次单击button1,为什么它的caption不会变,而memo1的内容会变。

解决方案 »

  1.   

    datathread.str:=button1.Caption;//为什么button1.caption不会变?
    是不是应该这样?button1.Caption:=datathread.str
      

  2.   

    不能直接这样调用,要用Synchronize 才能实现
      

  3.   

    因为你传递给 datathread.str 的是 button1.Caption 的值,所以之后更改 datathread.str 时,和 button1.Caption 没有任何关系。你要传递 button1.Caption 的地址给 datathread.str,这样才能通过 datathread.str 更改 button1.Caption 的值。但因为 button1.Caption 并不是一个变量,它实际上是对象的属性,属性不能简单地通过它的地址来修改值,所以你必须采用另一种方法:把 datathread.str 也定义成一个属性,通过设置属性的写方法来进行操作。根据你的上述代码修改如下:
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        Memo1: TMemo;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;  TClientDataThread = class(TThread)
      private
        fstr: string;
        procedure Setstr(const Value: string);
        procedure ChangeCaption;
      public
        TargetList :TStrings;
        property str: string read fstr write Setstr;
        procedure Execute; override;
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TClientDataThread.Execute;
    begin
      targetlist.Add('hello');
      str:='hello';
    end;procedure TClientDataThread.Setstr(const Value: string);
    begin
      fstr := Value;
      Synchronize(ChangeCaption);
    end;procedure TClientDataThread.ChangeCaption;
    begin
      Form1.Caption := fstr;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      DataThread:TClientDataThread;
    begin
      DataThread:=TClientDataThread.Create(true);
      DataThread.TargetList:=memo1.Lines;
      datathread.str:=button1.Caption;//为什么button1.caption不会变?
      DataThread.Resume;
    end;end.
      

  4.   

    to  DDGG:
    你的这个修改也不能让button1的caption变成hello,就算你把
    TClientDataThread.ChangeCaption里面的Form1.Caption:= fstr
    改成Form1.button1.Caption := fstr
    我想它的机制和DataThread.TargetList:=memo1.Lines也不一样吧。按照你的修改,现在str已经是属性了,满足你的话:“button1.Caption并不是一个变量,它实际上是对象的属性,属性不能简单地通过它的地址来修改值,所以你必须采用另一种方法:把datathread.str 也定义成一个属性,通过设置属性的写方法来进行操作。”我想问的是:为什么DataThread.TargetList:=memo1.Lines可以让memo1.lines变化而
    datathread.str:=button1.Caption却不可以?lines是memo1的属性,它是一个tstrings,所以定义一个
    TargetList :TStrings和它匹配;caption是button1的属性,它是一个string,所以定义一个
    str:string和它匹配。两者看起来是一样的,而要它们显示,却要用不同的方法,一个用
    DataThread.TargetList:=memo1.Lines,另一个用Synchronize(ChangeCaption)?????
      

  5.   

    大虾挥了挥手说,“小菜鸟,不系这样滴,,,procedure TForm1.Button1Click(Sender: TObject);
    var
      DataThread:TClientDataThread;
    begin
      DataThread:=TClientDataThread.Create(true);
      DataThread.TargetList:=memo1.Lines;
      {
        这里,你的DataThread.TargetList是一个对象引用
      }  datathread.str:=button1.Caption;//为什么button1.caption不会变?
      {
        这里,dataThread.str本身是一个字符串副本
        这面这句话只是将button1.caption的内容复制到dataThread.str
      }
      DataThread.Resume;
    end;procedure TClientDataThread.Execute;
    begin
      targetlist.Add('hello'); 
      {
        你这里通过对象引用调用Add方法,实际上调用的是Memo.Lines.Add()
        所以你看到输出
      }  str:='hello';
      {
        你这里只是将datathread.str的内容变成'hello'
        和button1.caption没有关系,所以button1.caption不会变
      }
    end;
      

  6.   

    是的,我上面的代码写错了,ChangeCaption() 里 Form1.Caption := fstr; 应该改为 Form1.button1.Caption := fstr; 就对了。至于你说的更改的机制不一样,这是没办法的,原因我上面已经说了。你说为什么 DataThread.TargetList:=memo1.Lines 后可以做到更改,那是因为 TStrings 类型恰巧是一个对象类型,它保存的变量实际上就是个地址。