我在D6+Winxp SP2下编写了以下程序,请问两个Edit的内容怎么不同步更新呢?
unit test1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    TrackBar1: TTrackBar;
    TrackBar2: TTrackBar;
    Label3: TLabel;
    Label4: TLabel;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;  TMyThread=class(tthread)
      Fm,Fn:integer;
      FEdit:TEdit;
      procedure Show;
      constructor create(m,n:Integer;myEdit:TEdit);
      procedure execute;override;
  end;
var
  Form1: TForm1;implementation{$R *.dfm}{ TMyThread }constructor TMyThread.create(m, n: Integer; myEdit: TEdit);
begin
  inherited create(false);
  Fm:=m;
  Fn:=n;
  FEdit:=myEdit;
  freeonterminate:=true; // 线程终止时自动删除对象,
end;procedure TMyThread.execute;
begin
  synchronize(show); // 线程调用同步
end;procedure TMyThread.Show;
var
  i:Integer;
begin
  for i:=Fm to Fn do
  begin
    FEdit.Text:='循环到:'+IntToStr(i);
    FEdit.Update;
  end;
end;procedure TForm1.Button1Click(Sender: TObject);
var
  T1,T2:TmyThread;
begin
  Edit1.Text:='';
  Edit2.Text:='';
  T1:=TMyThread.create(1,20000,Edit1);
  T2:=TMyThread.create(20001,50000,Edit2);
end;end.  

解决方案 »

  1.   

    另外,如果你的机器只有一个核(CPU的指令执行单元)的话,这两个线程还需要跟你的主线程,以及你操作系统当中其它的一些应用程序,一起串行执行。更不可能有你所期望的同步执行。
      

  2.   

    synchronize一般用在VCL组件操作时,所以如果您把synchronize写在循环中,也Show直接调用,应该可以得到你想到的效果.
      

  3.   

    也就是把
      FEdit.Text:= '循环到: '+IntToStr(i); 
      FEdit.Update; 
    写到另一个函数中,如:
    procedure XXX.UpdateEditor;
    begin
      FEdit.Text:= '循环到: '+IntToStr(i); 
      FEdit.Update; 
    end;
    再在循环体中这样调用:
    procedure TMyThread.Show; 
    var 
      i:Integer; 
    begin 
      for i:=Fm to Fn do 
      begin 
        synchronize(UpdateEditor);
      end; 
    end; 
      

  4.   

    难道楼上不知道synchronize是使用消息机制在主线程当中串行运行的?
      

  5.   

    把循环放在execute中,而不是Show中:type
      TMyThread=class(tthread) 
        Fm,Fn: Integer; 
        FEdit: TEdit; 
        i    : Integer;  
        procedure Show; 
        constructor create(m,n:Integer;myEdit:TEdit); 
        procedure execute;override; 
      end; procedure TMyThread.execute; 
    begin 
      for i := Fm to Fn do 
        synchronize(show);
    end; procedure TMyThread.Show; 
    begin 
      FEdit.Text:= '循环到: ' + IntToStr(i); 
      FEdit.Update; 
    end; 
      

  6.   

    jadeluo 和 seamansoft 说的难道不是一样的吗?晕!不要把什么东西说得那么玄,能解决问题才是关键!
      

  7.   

    “另外,如果你的机器只有一个核(CPU的指令执行单元)的话,这两个线程还需要跟你的主线程,以及你操作系统当中其它的一些应用程序,一起串行执行。更不可能有你所期望的同步执行。”从线程出世时,大多数PC都只有一个核。流水线也好,多核CPU也好,总要通过时间片来管理的,与其说“消息机制”,不如说控制临界资源好理解。synchronize就是用来处理VCL相关临界资源的,所以把VCL访问的代码放入到synchronize的函数中就行了。简单吧。
      

  8.   

    我所说的和 seamansoft 就是不一样的哇。 你没明白synchronize的原理,所以才会有这样的疑问。在execute中代码是按线程的方式运作的,也就是说它们是并行工作的。用synchronize调用的代码是在主线程中以消息机制、按串行方式工作的。你把循环放在synchronize中去执行的话,一个循环结束之前,另一个循环是不会开始的。当然,我上面给出的代码也有些问题,就是循环变量得是局部变量。修改如下:type
      TMyThread=class(tthread)
          Fm,Fn:integer;
          FEdit:TEdit;
          Fi   : Integer;
          procedure Show;
          constructor create(m,n:Integer;myEdit:TEdit);
          procedure execute;override;
      end;
    procedure TMyThread.execute;
    var
      i : Integer;
    begin
      for i := Fm to Fn do
      begin
        Fi := i;
        synchronize(show);
      end;
    end;procedure TMyThread.Show;
    begin
      FEdit.Text:= 循环到:'+IntToStr(Fi);
      FEdit.Update;
    end;你试一下就知道这样的代码是不是符合你的要求了。
      

  9.   

    jadeluo 和 seamansoft 说的难道不是一样的吗?晕!不要把什么东西说得那么玄,能解决问题才是关键!
    =========================
    他们两人的代码机制上面是有所差别的,如果不相信可以使用Spy++进行消息跟踪。
    流水线也好,多核CPU也好,总要通过时间片来管理的,与其说“消息机制”,不如说控制临界资源好理解。synchronize就是用来处理VCL相关临界资源的,所以把VCL访问的代码放入到synchronize的函数中就行了。简单吧。
    ==================
    多核讲求的就是多个线程同一时间片同并行执行,就好比两工人在工作。
    另外我所说的多核跟Synchronize是两回事。
    如果不懂得Synchronize的原理,可以看一下VCL当中相关的实现代码,或者搜索一下这个版块当中别的地址,前一段时间还有人专程发出相关的线程同步的贴子进行过讨论。http://topic.csdn.net/u/20070531/17/7c410df9-4aa5-4ed0-9227-159caedbad9a.html另外对于应用程序当中多线程的执行,既然这里面使用的是C++的代码,建议可以采用VC++/Intel C++进行编译,然后使用Intel的一个Thread Profiler相关工具进行线程执行流水线的分析。PS:
    1.我这并不是给Intel打广告,仅仅只是提供一种途径来了解多线程的运行状态。
    2.我上面说的要进行多线程的并行,而没有提Synchronize,只是为了解答楼主的问题,所以没有提出VCL的同步问题。实际上,在这样一个简单的程序当中完全可以不使用VCL同步,因为在这里面不会有多个线程对同一个Edit进行改写。线程同步需要同步的只是避免多个线程的写竞争。
      

  10.   

    经过测试,Seamansoft和jadeluo的确有区别------jadeluo的是可行的。请Seamansoft试试?
    对于unsigned提到的一个核(CPU),实际程序只能串行执行的问题,我又加了几句代码,用GetTickcount测试了在用多线程(如上代码)和在非多线程(如下)代码下执行的时间,发现在非多线程下的效率还要快些。我的疑惑是:还有必要使用多线程吗?(费话,肯定有必要了)那在哪些情况下需要用多线程来实现呢?
    procedure TForm1.Button2Click(Sender: TObject);
    var
      i:Integer;
    begin
      T_start:=GetTickCount;
      for i:=1 to 20000 do
      begin
        Edit1.Text:='循环到:'+IntToStr(i);
        Edit1.Update;
      end;
      for i:=20001 to 40000 do
      begin
        Edit2.Text:='循环到:'+IntToStr(i);
        Edit2.Update;
      end;
      ShowMessage(IntToStr(GetTickCount-T_start));
    end;
      

  11.   

    多线程使用的必要性当中的什么等待慢速设备之类的,我就不多提了,各式各样的资料当中都有说明。
    比如楼上的问题当中,实际上很显而易见的就是把一个大的循环作业分成多个线程去做。通常情况下我们说,一个循环,只要前一步运算结果与后一步的运算结果互不影响(不是没有联系)就可以把它分成多个任务,从而让多个人,在这里可以假定为多台电脑(如果运算强度比较大的话,这也是可行的)去完成。在同一台机器上面,则我们说得比较多的就是多进程和多线程,而对于进程来讲,分配的资源会比较多,并且启动和销毁,数据同步等开销相当大,所以在能使用多线程的情况下尽可能采用多线程。但是线程也并不是越多越好,否则的话,多个线程共享同一个CPU,那么指令在CPU当中同样是串行的,而这个线程的切换是有相当开销的,反倒有可能引起性能下降。而推荐的情况就是当没有低速设备参与的情况下,一般地就是根据CPU的并行能力,通俗一点,就目前来讲,那就是逻辑核个数。这样子才能达到真正并行处理的目的。