delphi - 延迟检测用 TThread.ForceQueue() 调用的已释放对象
问题描述
当您在a中时TFrame
,您TThread.ForceQueue(nil, MyFrame.OneProc, 200)
如何检查同时没有被破坏的MyFrame.OneProc
程序MyFrame
?
换句话说,在这种常见的场景中可以使用什么机制?
解决方案
您可以使用监护人接口,该接口将成为功能齐全的实例,您可以使用它来检查受保护对象是否同时被释放。
type
IGuardian = interface
function GetIsDismantled: Boolean;
procedure Dismantle;
property IsDismantled: Boolean read GetIsDismantled;
end;
TGuardian = class(TInterfacedObject, IGuardian)
private
FIsDismantled: Boolean;
function GetIsDismantled: Boolean;
public
procedure Dismantle;
property IsDismantled: Boolean read GetIsDismantled;
end;
procedure TGuardian.Dismantle;
begin
FIsDismantled := True;
end;
function TGuardian.GetIsDismantled: Boolean;
begin
Result := FIsDismantled;
end;
然后你需要在你的框架中添加监护人字段
type
TMyFrame = class(TFrame)
private
FGuardian: IGuardian;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property Guardian: IGuardian read FGuardian;
end;
constructor TMyFrame.Create(AOwner: TComponent);
begin
inherited;
FGuardian := TGuardian.Create;
end;
destructor TMyFrame.Destroy;
begin
// prevent AV when destroying partially
// constructed instance
if Assigned(FGuardian) then
FGuardian.Dismantle;
inherited;
end;
但是您不能直接对帧进行排队MyProc
,您需要使用匿名方法并捕获该监护人变量,以便其生命周期超出框架的生命周期。
引用计数将保持监护对象实例即使在MyFrame
被释放后仍处于活动状态,并且其内存将被自动管理。
使用本地声明的Guardian
接口变量并捕获该变量而不是直接捕获字段很重要,因为该字段地址在释放MyFrame.Guardian
后将不再有效。MyFrame
procedure CallMyProc;
var
Guardian: IGuardian;
begin
Guardian := MyFrame.Guardian;
TThread.ForceQueue(nil,
procedure
begin
if Guardian.IsDismantled then
Exit;
MyFrame.OneProc;
end, 200);
end;
注意:即使您TThread.Queue
没有延迟使用,也有可能在排队过程运行之前释放帧。所以你需要保护你的框架也是这样的场景。
推荐阅读
- php - 从 PHP 数组中获取值并显示它们
- kubernetes - 调用 kubectl cp 命令时如何使用 tar 命令选项
- node.js - 跟踪 nodemon 中的 yaml 文件更改
- javascript - 获取的承诺未执行
- javascript - 了解 koa-passport 使用 IIFE 进行身份验证
- node.js - Firebase 函数 onCreate 未触发
- javascript - Google Sheets Node.js 快速入门指南:如何将从 API 返回的行数组返回到变量中
- java - 在 Bitbucket 上托管的 Maven 项目上,我应该在哪里为 Azure DevOps 管道设置 Nexus 凭据?
- javascript - WebGl“错误:不支持的着色器版本”
- php - 1m 后脚本被破坏,状态失败,PHP-Apache 使用 AWS SES 发送电子邮件时