1

我想子类化TThread,以便有一个线程类,当 时FreeOnTerminate = True,设置nil为其引用变量。换句话说,我想做这样的事情:

TFreeAndNilThread = class(TThread)
private
  FReferenceObj: TFreeAndNilThread;  //??  // <-- here I'm holding the reference to myself
protected
  procedure Execute;
  procedure DoTerminate; override;  // <-- here I'll set FReferenceObj to nil after inherited (only if FreeAndNil = True)
public
  constructor Create(CreateSuspended: Boolean; var ReferenceObj); reintroduce;  <-- untyped param like FreeAndNil and TApplication.CreateForm ??
end;

消费者代码应该是这样的:

var
  MyThread: TFreeAndNilThread;

begin
  MyThread := TFreeAndNilThread.Create(True, MyThread);
  MyThread.FreeOnTerminate := True;
  MyThread.Resume;
end;

...然后我可以安全地测试Assigned(MyThread).

我看到如何FreeAndNil设法将无类型参数传递的引用对象设置为nil,但它在本地执行此操作。在我的情况下,我应该将它“保存”到一个类字段 ( FReferenceObj) 并在另一个地方 ( ) 使其为零DoTerminate

如何正确传递、存储和检索它?我可以考虑传递和存储 MyThread 的地址而不是 MyThread 本身,但我希望有更优雅的方式。

谢谢!

4

1 回答 1

1

您需要存储指向变量的指针。

type
  TFreeAndNilThread = class(TThread)
  private
    FReferenceObj: ^TFreeAndNilThread;
  end;

然后需要在构造函数中传入引用:

type
  TFreeAndNilThread = class(TThread)
  private
    FReferenceObj: ^TFreeAndNilThread;
  public
    constructor Create(var ReferenceObj: TFreeAndNilThread);
  end;

然后你可以像这样实现它:

constructor TFreeAndNilThread.Create(var ReferenceObj: TFreeAndNilThread);
begin
  inherited Create(True);
  FreeOnTerminate := True;
  FReferenceObj := @ReferenceObj;
end;

当线程死亡时,您将引用设置为nil

ReferenceObj^ := nil;

为方便起见,由于您可能会将其视为派生其他​​类的基类,因此您可能更愿意将构造函数的参数设为无类型。您可以这样做,而无需对代码进行其他更改。当你这样做时,构造函数如下所示:

constructor Create(var ReferenceObj);

nil如果设置引用的代码与所有其他尝试引用的代码位于同一线程中,这只会对您有好处MyThread。否则你将有一个竞争条件。

我相当确定您的想法不是解决问题的方法。但是,上面确实向您展示了如何引用变量,这是您所要求的。

于 2013-09-12T08:18:14.987 回答