【问题标题】:How to free an object inside its event handler?如何在其事件处理程序中释放对象?
【发布时间】:2015-04-11 10:23:41
【问题描述】:

我有 TMyClass,一个从 TObject 派生的类。它有一个 TTimer。每隔几分钟,我会从 Timer.OnTimer 检查一个网页。当网页发生变化时,我就完成了,我想释放 MyClass。如何释放它?

我的问题类似于this 之一,但我的“控件”不是 TControl。它是 TObject 的后代。因此,消息将不起作用。 显然,解决方案是从 TControl 或更高版本派生我的类。但是,假设我不想这样做。这种情况下的解决方案是什么?

【问题讨论】:

  • 等等,所以你没有持有对这些对象的引用(当应用程序终止时你正在泄漏它们)?如果你这样做了,并且对象从内部释放了自己,那么引用之后就会变成一个悬空指针(然后你尝试在其上调用Free)。您应该考虑某种对象管理器并要求该管理器释放对象(并将其从其引用集合中删除)。

标签: delphi


【解决方案1】:

使用消息背后的基本思想是正确的:确保在当前调用它的任何代码完成之后,该对象在稍后被释放。

几年前,我写了一个Delayed Action 单元,它为您提供了一种无需 TControl 即可实现相同效果的简单方法。您只需调用 DelayExec 并向其传递一个匿名方法,该方法将释放该对象,它会在内部设置一条消息,以便在消息队列被抽出后立即执行。

【讨论】:

  • 尽可能简单。灵活多变。
  • 谢谢梅森。这就是我需要的。
【解决方案2】:

要接收消息,您需要有窗口句柄。您可以使用AllocateHWnd 分配一个,类似于

type
  TMyClass = class(TObject)
  private
    FHandle: HWND;
    procedure MyWndProc(var Msg: TMessage);
  public
    constructor Create; virtual;
    destructor Destroy; override;
  end;

constructor TMyClass.Create();
begin
  inherited Create();
  FHandle := AllocateHWnd(myWndProc);
end;

destructor TMyClass.Destroy;
begin
  DeallocateHWnd(FHandle);
  inherited;
end;

procedure TMyClass.MyWndProc(var Msg: TMessage);
begin
  case Msg.Msg of
    CM_RELEASE: begin
       Free;
    end;
    else Msg.Result := DefWindowProc(FHandle, Msg.Msg, Msg.WParam, Msg.LParam);
  end;
end;

现在您可以使用FHandle 向对象发布消息,如您引用的帖子中所示。

【讨论】:

  • 请注意TMyClass.Create 只能从主线程调用,因为AllocateHWnd 有这个限制。使用AllocateHWnd 的定制版本可以解决这个问题。当然,您可能只希望在主线程上调用 TMyClass 的方法,所以这几乎肯定不是您关心的问题。
  • ...你会产生一个悬空指针。这个答案是正确的,自毁(非接口)对象的想法很糟糕。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-29
  • 2010-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多