为什么这种方式不行?procedure TMyThread.Execute;
begin
  while not Terminated do
  begin
      if tick <= 10000 then begin
        EnterCriticalSection(CriticalSection);
        try
          Form1.Edit1.Text :=IntToStr(tick);
          Inc(tick);
        finally
          LeaveCriticalSection(CriticalSection);
        end;
      end;
  end;
end;procedure TForm1.Button1Click(Sender: TObject);
var
  Mythread:TMyThread;
begin
  tick:=1;
  Mythread :=TMyThread.Create(False);
end;procedure TForm1.FormCreate(Sender: TObject);
begin
InitializeCriticalSection(CriticalSection); //初始化
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
 DeleteCriticalSection(CriticalSection); //删除
end;
为什么下边这种方法可以
procedure TMyThread.AddEdit;
begin
  Form1.Edit1.Text :=IntToStr(tick);
  Inc(tick);
end;procedure TMyThread.Execute;
begin
  while not Terminated do
  begin
      if tick <= 10000 then begin
        Synchronize(addedit);
      end;
  end;
end;procedure TForm1.Button1Click(Sender: TObject);
var
  Mythread:TMyThread;
begin
  tick:=1;
  Mythread :=TMyThread.Create(False);
end;procedure TForm1.FormCreate(Sender: TObject);
begin
InitializeCriticalSection(CriticalSection); //初始化
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
 DeleteCriticalSection(CriticalSection); //删除
end;

解决方案 »

  1.   

    本帖最后由 bdmh 于 2010-09-01 10:24:15 编辑
      

  2.   

    哦,抱歉,我看错函数了,呵呵,上面的解释和你的问题不一样,现在重新来。
    Form1.Edit1.Text :=IntToStr(tick);
    Inc(tick);这部分是在管道中要保护的部分,你在子线程中,实现了保护,但是,你在主线程中,没有对其进行保护,至少Form1.Edit1.Text这个没有被保护,这样,虽然你使用了临界,但是对Form1.Edit1.Text的操作依然会存在多线程(主线程和子线程)同时访问的情况。
    而Synchronize却可以保证这种同步,也就是被Synchronize所指定的那个过程,会在主线程中被调用。
      

  3.   

    虽然这个帖子已经结了,我还是要跟一下。
    下面的代码是我依据楼主第一段代码复原的。在TMyThread.Execute方法中有我的注释,证明了某些人的理论是伪理论!
    TEdit控件封装自Windows系统控件Edit,它依靠复杂的消息传递来操作。而消息传递只在主线程进行,但是子线程TMyThread不管,它以最快的速度给TEdit赋值,在主线程的消息来不及处理的情况下冲突报错。用Sleep(1)可以给一些消息处理的时间,可能就避免了报错。同理,并不是所有的控件都会报错,有些控件的消息处理较简单,可能还能跟得上子线程TMyThread。比如给Form1.Caption赋值。可能我说的也不完全对,请各位指正。
    最后我想请各位以严谨的心态回帖,不要只是想多得些分。unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TMyThread = class(TThread)
      protected
        procedure Execute; override;
      end;  TForm1 = class(TForm)
        Button1: TButton;
        Edit1: TEdit;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      CriticalSection: TRTLCriticalSection;
      tick: Integer;implementation{$R *.dfm}{ TMyThread }procedure TMyThread.Execute;
    begin
      while not Terminated do
      begin
          if tick <= 1000 then begin
            EnterCriticalSection(CriticalSection);
            try
              Sleep(1); {加上此行就不会报错了}
              //Form1.Caption :=IntToStr(tick); {或者把下一行替换为此行也不会报错}
              Form1.Edit1.Text :=IntToStr(tick);
              Inc(tick);
            finally
              LeaveCriticalSection(CriticalSection);
            end;
          end;
      end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      Mythread:TMyThread;
    begin
      tick:=1;
      Mythread :=TMyThread.Create(False);
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
    InitializeCriticalSection(CriticalSection); //初始化
    end;procedure TForm1.FormDestroy(Sender: TObject);
    begin
     DeleteCriticalSection(CriticalSection); //删除
    end;end.
      

  4.   

    在我的机器上运行楼主的原代码,报错前,Form1.Edit1.Text能跑到50~80。