[英]TForm management in Spring4D
我有以下代碼:
Project.dpr
program Project2;
uses
madExcept,
madLinkDisAsm,
madListHardware,
madListProcesses,
madListModules,
Spring.Container,
Vcl.Forms,
uRegistrations in '..\Memory leak II\uRegistrations.pas',
Unit3 in 'Unit3.pas' {MainForm},
Unit4 in 'Unit4.pas' {SecondaryForm},
Unit5 in 'Unit5.pas';
{$R *.res}
begin
RegisterTypes(GlobalContainer);
Application.Initialize;
Application.MainFormOnTaskbar := True;
// MainForm:=TMainForm.Create(nil);
Application.CreateForm(TMainForm, MainForm);
MainForm.SecondaryForm := Globalcontainer.Resolve<ISecondaryForm>;
Application.Run;
end.
注冊接口的uRegistrations.pas
unit uRegistrations;
interface
uses
Spring.Container;
procedure RegisterTypes(Container: TContainer);
implementation
uses
Unit5,
Unit4;
procedure RegisterTypes(Container: TContainer);
begin
container.RegisterType<ISecondaryForm, TSecondaryForm>.DelegateTo(
function: TSecondaryForm
begin
result := TSecondaryForm.Create(nil);
end);
Container.Build;
end;
end.
Unit3.pas持有的主要形式
unit Unit3;
interface
uses
Winapi.Windows,
Winapi.Messages,
System.SysUtils,
System.Variants,
System.Classes,
Vcl.Graphics,
Unit5,
Vcl.Controls,
Vcl.Forms,
Vcl.Dialogs;
type
TMainForm = class(TForm)
private
{ Private declarations }
FSecondaryForm: ISecondaryForm;
public
{ Public declarations }
property SecondaryForm: ISecondaryForm read FSecondaryForm write FSecondaryForm;
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
end.
具有輔助形式的Unit4.pas
unit Unit4;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
unit5,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
type
TSecondaryForm = class(TForm, ISecondaryForm)
private
{ Private declarations }
public
{ Public declarations }
end;
//var
// SecondaryForm: TSecondaryForm;
implementation
{$R *.dfm}
end.
最后是帶有接口聲明的Unit5.pas
{$M+}
unit Unit5;
interface
type
ISecondaryForm=interface
['{62D63E9A-A3AD-435B-8938-9528E70D78B1}']
end;
implementation
end.
它可以編譯並正常運行,但是當我關閉應用程序時,我遇到了三個內存泄漏。
分配編號:8482程序啟動時間:721 ms類型:畫筆手柄句柄:$ 461027f5樣式:BS_SOLID顏色:$ f0f0f0
分配編號:8318程序運行時間:697 ms類型:TSecondary表格地址:$ d51ac64大小:924訪問權限:讀/寫
分配編號:8267程序運行時間:693 ms類型:字體句柄句柄:$ 1d0a28f1面孔:Tahoma高度:-11
為什么會發生這種情況,我該如何解決?
編輯
回答之后,我實現了以下解決方案(這些注釋突出了我得到的錯誤:
procedure RegisterTypes(Container: TContainer);
begin
container.RegisterType<ISecondaryForm, TSecondaryForm>.DelegateTo(
function: TSecondaryForm
begin
result := TSecondaryForm.Create(nil);
result.Owner:=Application.MainForm;//cannot assign to a read-only property
result.Parent:=Application; //incompatible types
result.Parent:=application.MainForm;//memory leak
end);
Container.Build;
end;
我還嘗試通過以下方式修改TSecondaryForm的OnClose方法:
procedure TSecondaryForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree; //memory leak
end;
但是我發生了內存泄漏。
我上面的所有技術在做什么?
最后,我按照注釋中的建議使用了_AddRef和_Release這兩種方法來管理引用計數,並且不再發生內存泄漏。
TSecondaryForm = class(TForm, ISecondaryForm)
private
{ Private declarations }
protected
FRefCount: Integer;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
{ Public declarations }
end;
function TSecondaryForm._AddRef: Integer;
begin
Result := InterlockedIncrement(FRefCount);
end;
function TSecondaryForm._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if Result=0 then
self.Free;
end
如果您希望通過接口引用計數來處理表單(或從TComponent繼承的任何類),則需要自己實現(請參閱System.TInterfacedObject
作為該方法的示例)。
基本上,您需要為要啟用引用的類重新實現IInterface
:
type
TInterfacedForm = class(TForm, IInterface)
// look at System.TInterfacedObject
end;
如果要這樣做,請記住,所有者機制不應處理該問題。 如果將其注冊到容器並使用其默認創建機制,則從Spring4D 1.2開始,它將nil傳遞給所有者-請參見Spring.Container.Resolvers.TComponentOwnerResolver
)。 在任何版本中,您都需要在DelegateTo
內部使用nil顯式創建它。
如果您正在處理通過其父屬性放到其他控件(如框架)上的接口的任何控件,請記住,在這種情況下,另一種內存管理機制將發揮作用,如果該組件的父對象被破壞,則該內存管理機制可能會破壞該組件。 -如果您只是在處理接口表單,那不是問題,但是我想我在這里提到是為了完整性。
TComponent
后代(如TForm
)禁用接口的引用計數,因此沒有人正在釋放二次形式。 內存模型是基於所有者的,也就是說,當擁有一個對象的父對象被釋放時,它將釋放它的所有子對象。
因此,您可以將所有者傳遞給工廠函數(可能是Application
或Application.MainForm
)上的表單,並遵循TComponent的內存模型,或者在表單的OnClose
事件上添加一個鈎子並將Action
設置為caFree
。 前者將在關閉應用程序時銷毀表單,后者將在第二個表單關閉時銷毀它(盡快)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.