本人第一次使用Delphi的线程,就是很简单的点按钮,然后启动一个线程
但是在点击按钮后,再关闭窗口就会出错,
如果线程还没执行完,我就关闭,会出现如下提示
   Thread Error: 句柄无效(6)
执行完后,在关闭,会出现如下提示:
   Access Violation at address *******
代码如下,请指点,谢谢
unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;type
  TThread1 = class(TThread)
    protected
      procedure Execute; override;
  end;  TForm1 = class(TForm)
    Button1: TButton;
    mmo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    t1: TThread1;
  public
    { Public declarations }
  end;var
  Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
  t1 := TThread1.Create(False);
end;{ TThread1 }procedure TThread1.Execute;
var
  i: Integer;
begin
  FreeOnTerminate := True;
  try
    for i := 0 to 9999 do
    begin
      Form1.mmo1.Lines.add(IntToStr(i));
    end;
  except  end;
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Assigned(t1) then
  begin
    t1.Terminate;
    FreeAndNil(t1);
  end;
end;end.

解决方案 »

  1.   

    点按钮的时候创建了
    t1 := TThread1.Create(False);
      

  2.   


    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TThread1 = class(TThread)
      private
        FIndex: Integer;
        procedure LinesAdd();
      protected
        procedure Execute; override;
      end;  TForm1 = class(TForm)
        Button1: TButton;
        mmo1: TMemo;
        procedure Button1Click(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        { Private declarations }
        t1: TThread1;
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TThread1.LinesAdd();
    begin
      Form1.mmo1.Lines.add(IntToStr(FIndex));
    end;procedure TThread1.Execute;
    var
      i: Integer;
    begin
      FreeOnTerminate := True;
      for i := 0 to 9999 do
      begin
        if Terminated then break;
        FIndex := i;
        Synchronize(LinesAdd);
      end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      t1 := TThread1.Create(False);
    end;procedure TForm1.FormDestroy(Sender: TObject);
    begin
      if Assigned(t1) then t1.Terminate;
    end;end.
      

  3.   

    是不是最后的t1.free的原因啊还有就是Synchronize能简单解释一下作用或原理吗
      

  4.   

    t1.terminate不是只是将FTerminated置为true,没有释放吗?
      

  5.   

    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      if Assigned(t1) then
      begin
        t1.Terminate;
        t1.WaitFor;
        t1 := nil;
      end;
    end;
      

  6.   

    3楼正解!
    LZ代码错误百出!
    function ThreadProc(Thread: TThread): Integer;
    var
      FreeThread: Boolean;
    begin
      try
        if not Thread.Terminated then
        try
          Thread.Execute;
        except
          Thread.FFatalException := AcquireExceptionObject;
        end;
      finally
        FreeThread := Thread.FFreeOnTerminate;
        Result := Thread.FReturnValue;
        Thread.DoTerminate;
        Thread.FFinished := True;
        SignalSyncEvent;
        if FreeThread then Thread.Free;
    //
    1.
    由VCL以上代码可以看出在FreeOnTerminate为True时,当执行完毕线程后,会把堆内存释放,但并没有把栈指针清空,而LZ在窗口关闭时又进行了一次线程对象的Free,这样,即使你等线程正常处理完毕后,再关闭窗体仍然会出错的!
    2.
    在遇到线程中途退出时,应遵循循环等待并判断退出标识的策略,而不是中途无判断!
    3.
    操作VCL时无同步
    {$IFDEF MSWINDOWS}
        EndThread(Result);
    {$ENDIF}
      end;
    end;