type
  TMyThread = class(TThread)
  protected
    procedure Execute; override;
    procedure SetValue;
  public
end;procedure TMyThread.Execute;
begin
  FreeOnTerminate := True;
  Synchronize(SetValue);
end;procedure TMyThread.SetValue;
var
  i: Integer;
begin
  for i := 0 to 100000 do
  begin
    Application.ProcessMessages;
    if self.Terminated then Break;
    form1.Edit1.Text := IntToStr(i);
  end;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
  MyThread := TMyThread.Create(false);
end;procedure TForm1.Button2Click(Sender: TObject);
begin
  MyThread.Suspend;//???怎么停不下来
end;为什么执行MyThread.Suspend后线程还是在运行,根本没挂起???请指教,谢谢

解决方案 »

  1.   

    procedure TMyThread.SetValue;
    var
      i: Integer;
    begin
      for i := 0 to 100000 do
      begin
      Application.ProcessMessages;
      if self.Terminated then Break;
      form1.Edit1.Text := IntToStr(i);
      end;
    end;在你线程Suspend的时候,这里是不受影响的,它还是会继续执行procedure TMyThread.Execute;
    var
      i :Integer;
    begin
      FreeOnTerminate := True;
      for i := 0 to 100000 do
      begin
      Application.ProcessMessages;
      if self.Terminated then Break;
      form1.Edit1.Text := IntToStr(i);
      end;
    end;这样就能看到效果,但是线程中不推荐操作VCL,另外 Synchronize方法一般是受信主线程中操作VCL的方法。
      

  2.   

    procedure TMyThread.Execute;
    begin
      FreeOnTerminate := True;
      Synchronize(SetValue);
    end;Synchronize 这么写是不行的,等于把操作放到主线程去执行了,你自己线程控制不了
      

  3.   

    你把操作全放到主线程了,跟没用线程一样。
    应该像我这样用线程。procedure TMyThread.Execute;
    begin
      FreeOnTerminate := True;
    for i := 0 to 100000 do
      Synchronize(SetValue);
    end;
    procedure TMyThread.SetValue;
    var
      i: Integer;
    begin
      if self.Terminated then Break;
      form1.Edit1.Text := IntToStr(i);
    end;
      

  4.   

    楼上说'你把操作全放到主线程了'??????
    为什么同样是操作form1.Edit1,Synchronize(SetValue)是放到主线程中,而第二种不是了???
      

  5.   

    我给你讲讲吧Synchronize 是VCL中所谓线程同步方法
    procedure TThread.Synchronize(Method: TThreadMethod);
    begin
    // FSynchronize是一个结构体, 里边保存线程对象和要执行的函数
      FSynchronize.FThread := Self;
      FSynchronize.FSynchronizeException := nil;
      FSynchronize.FMethod := Method;
      Synchronize(@FSynchronize);  // 这里才是最主要的
    end;
    // 我把Linux下的代码删了
    class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord);
    var
      SyncProc: TSyncProc;
    begin
      if GetCurrentThreadID = MainThreadID then
        ASyncRec.FMethod   // 如果当前是主线程,执行你要执行的同步函数
      else
      begin
    {$IFDEF MSWINDOWS}     // 当前线程不是主线程,则执行下边的
        SyncProc.Signal := CreateEvent(nil, True, False, nil);  // 创建一个事件, 无信号状态。
        try
    {$ENDIF}
          // 进入临界区
          EnterCriticalSection(ThreadLock);
          try
            if SyncList = nil then
              SyncList := TList.Create;
            SyncProc.SyncRec := ASyncRec;
            SyncList.Add(@SyncProc);  // 这段主要是用一个列表保存要同步的函数,用临界区保护起来
            SignalSyncEvent;          // 将事件设为有信号
             // WakeMainThread 是个全局变量 , 在FORM单元里赋值,里边过程有点小复杂,
            if Assigned(WakeMainThread) then  
              WakeMainThread(SyncProc.SyncRec.FThread); // 在这里边执行同步函数
    {$IFDEF MSWINDOWS}
            LeaveCriticalSection(ThreadLock);  // 离开临界区 
            try
              WaitForSingleObject(SyncProc.Signal, INFINITE); // 等待结束
            finally
              EnterCriticalSection(ThreadLock);
            end;
    {$ENDIF}
          finally
            LeaveCriticalSection(ThreadLock);
          end;
    {$IFDEF MSWINDOWS}
        finally
          CloseHandle(SyncProc.Signal);
        end;
    {$ENDIF}
        if Assigned(ASyncRec.FSynchronizeException) then raise ASyncRec.FSynchronizeException;
      end;
    end;
    你暂停不了是因为要同步的函数已经被赋给全局变量了,你暂停只是暂停了你的线程