【delphi线程】 如何自动释放?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【delphi线程】 如何自动释放?相关的知识,希望对你有一定的参考价值。

我在线程里面 写了一个循环。
a:=0;
while a<1000 do
begin
if a=999 then
begin
//停止线程,释放线程 这里应该怎么写?
end;
end;
求大神

1.线程的构造函数里FreeOnTerminate:=True
2.重载基类的Execute方法,在次方法里实现线程要做的事。
这样设置后,你的线程在Execute方法被自动调用后就会被自动释放了。
参考技术A 那里写:
Terminate;

Delphi 中的自动释放策略

来自万一老师的博客:http://www.cnblogs.com/del/archive/2011/12/21/2295794.html

--------------------------------------------------------------------------------------------------

一、指定 Owner 后, 随 Owner 连带释放:


 

//uses Vcl.StdCtrls, Vcl.ExtCtrls;

var
  panel: TPanel;

procedure TForm1.Button1Click(Sender: TObject);
begin
  panel := TPanel.Create(Self);
  panel.Parent := Self;

  with TButton.Create(panel) do //AOwner = panel
  begin
    Parent := panel;
    Caption := \'New Button\';
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if Assigned(panel) then
    FreeAndNil(panel); //连带释放以它为 Owner 的对象
end;


二、使用接口:


 

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

  //
  IBass = Interface
    function GetName: string;
    procedure SetName(const AName: string);
    property Name: string read GetName write SetName;
  end;

  //
  TBass = class(TInterfacedObject, IBass)
  private
    FName: string;
  protected
    function GetName: string;
    procedure SetName(const AName: string);
  public
    constructor Create(const AName: string);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  X: IBass;
begin
  X := TBass.Create(\'WanYi\');
  ShowMessage(X.Name);
  X.Name := \'万一\';
  ShowMessage(X.Name);
  {X 在此自动释放}
end;

{ TBass }

constructor TBass.Create(const AName: string);
begin
  FName := AName;
end;

function TBass.GetName: string;
begin
  Result := FName;
end;

procedure TBass.SetName(const AName: string);
begin
  FName := AName;
end;

end.


三、使用结构:


 

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

  //
  TBass = record
  private
    FName: string;
    procedure SetName(const AName: string);
  public
    constructor Create(const AName: string);
    property Name: string read FName write SetName;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  X: TBass;
begin
  X := TBass.Create(\'WanYi\');
  ShowMessage(X.Name);
  X.Name := \'万一\';
  ShowMessage(X.Name);
  {X 在此自动释放}
end;

{ TBass }

constructor TBass.Create(const AName: string);
begin
  FName := AName;
end;

procedure TBass.SetName(const AName: string);
begin
  FName := AName;
end;

end.


四、在 initialization 中建立、在 finalization 中释放:


 

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  List: TStringList;

procedure TForm1.Button1Click(Sender: TObject);
begin
  List.Clear;
  List.Add(\'WanYi\');
  ShowMessage(List.Text);
end;

initialization
  List := TStringList.Create;
finalization
  List.Free;

end.


五、使用动态数组而不是 TList、TStringList 等:


 

procedure TForm1.Button1Click(Sender: TObject);
var
  arr: Array of string;
  i: Integer;
  s: string;
begin
  for i := 0 to 6 do
  begin
    SetLength(arr, Length(arr)+1);
    arr[High(arr)] := StringOfChar(Char(i+65), 3);
  end;
  for s in arr do ShowMessage(s);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  arr: TArray<string>;
  i: Integer;
  s: string;
begin
  for i := 0 to 6 do
  begin
    SetLength(arr, Length(arr)+1);
    arr[High(arr)] := StringOfChar(Char(i+65), 3);
  end;
  for s in arr do ShowMessage(s);
end;


六、使用 TObjectList 而不是 TList:


 

uses System.Contnrs;

procedure TForm1.Button1Click(Sender: TObject);
var
  list: TObjectList;
  i: Integer;
  btn: TButton;
begin
  list := TObjectList.Create;
  for i := 0 to 6 do
  begin
    btn := TButton.Create(Self);
    with btn do begin
      Caption := Format(\'Btn %d\', [i+1]);
      Parent := Self;
      Top := Height * i;
      Left := Width * i div 2;
    end;
    list.Add(btn);
  end;
  ShowMessage(\'TObjectList 释放时, 会同时释放其中的对象\');
  list.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  list: TList;
  i: Integer;
  btn: TButton;
begin
  list := TList.Create;
  for i := 0 to 6 do
  begin
    btn := TButton.Create(Self);
    with btn do begin
      Caption := Format(\'Btn %d\', [i+1]);
      Parent := Self;
      Top := Height * i;
      Left := Width * i div 2;
    end;
    list.Add(btn);
  end;
  ShowMessage(\'TList 释放后, 其中的对象并未释放\');
  list.Free;
end;


七、使用 TObjectList<T> 而不是 TList<T>:


 

uses System.Generics.Collections;

procedure TForm1.Button1Click(Sender: TObject);
var
  list: TObjectList<TButton>;
  i: Integer;
  btn: TButton;
begin
  list := TObjectList<TButton>.Create;
  for i := 0 to 6 do
  begin
    btn := TButton.Create(Self);
    with btn do begin
      Caption := Format(\'Btn %d\', [i+1]);
      Parent := Self;
      Top := Height * i;
      Left := Width * i div 2;
    end;
    list.Add(btn);
  end;
  ShowMessage(\'TObjectList 释放时, 会同时释放其中的对象\');
  list.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  list: TList<TButton>;
  i: Integer;
  btn: TButton;
begin
  list := TList<TButton>.Create;
  for i := 0 to 6 do
  begin
    btn := TButton.Create(Self);
    with btn do begin
      Caption := Format(\'Btn %d\', [i+1]);
      Parent := Self;
      Top := Height * i;
      Left := Width * i div 2;
    end;
    list.Add(btn);
  end;
  ShowMessage(\'TList 释放后, 其中的对象并未释放\');
  list.Free;
end;


八、使用结构体而不是结构体指针:


 

{假如某个函数的参数需要一个结构指针}
function Area(rect: PRect): Integer;
begin
  Result := rect.Width * rect.Height;
//  Result := rect^.Width * rect^.Height;
end;

{直接声明指针并分配空间后需手动释放}
procedure TForm1.Button1Click(Sender: TObject);
var
  P: PRect;
begin
  New(P);
  P^ := Rect(10, 10, 60, 50);
  ShowMessage(IntToStr(Area(P))); //2000
  Dispose(P);
end;

{}
procedure TForm1.Button2Click(Sender: TObject);
var
  R: TRect;
begin
  R := Rect(10, 10, 60, 50);
  ShowMessage(IntToStr(Area(@R))); //2000
end;

以上是关于【delphi线程】 如何自动释放?的主要内容,如果未能解决你的问题,请参考以下文章

DELPHI 用TThread如何判断线程是不是存在 并且释放线程

简单说说Delphi中线程的释放

Delphi,如何在 TList 中释放记录

如何释放接口对象 (Delphi 7)

delphi释放窗体后如何再次载入窗体

delphi 线程教学第四节:多线程类的改进