Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi Spring4D中的TForm管理_Delphi_Spring4d - Fatal编程技术网

Delphi Spring4D中的TForm管理

Delphi Spring4D中的TForm管理,delphi,spring4d,Delphi,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' {Ma

我有以下代码:

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.
第4单元带第二形式的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.
它定期编译和运行,但当我关闭应用程序时,我有三个内存泄漏

  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
分配编号:8482程序启动时间:721毫秒类型:刷柄 手柄:$461027f5样式:BS_纯色:$F0

分配编号:8318程序启动时间:697毫秒类型:t辅助表格 地址:$d51ac64大小:924访问权限:读/写

分配编号:8267程序启动时间:693毫秒类型:字体句柄 手柄:$1d0a28f1面:塔荷马高度:-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;
但是我的内存泄漏了

以上所有技术我做错了什么

最后,我只是让这两种方法\u AddRef\u 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
子体(如
TForm
)禁用接口引用计数,因此没有人释放辅助窗体。内存模型是基于所有者的,也就是说,当释放拥有对象的父对象时,它会释放其所有子对象

因此,您可以在factory函数中将所有者传递给表单(可能是
Application
,或者
Application.MainForm
)并遵循TComponent的内存模型,或在窗体的
OnClose
事件上添加一个钩子,并将
Action
设置为
caFree
。前者将在应用程序关闭时销毁窗体,后者将在次窗体关闭时(尽快)销毁窗体(或从TComponent继承的任何类)将由接口引用计数处理,然后您需要自己实现它(查看
System.TInterfacedObject
作为如何实现的示例)

基本上,您需要将
IInterface
重新实现到要启用引用计数的类:

type
  TInterfacedForm = class(TForm, IInterface)
    // look at System.TInterfacedObject
  end;
如果您这样做,请记住,它不应该由所有者机制处理。如果您将其注册到容器并使用其默认创建机制,它将从Spring4D 1.2起将nil传递给所有者-请参阅
Spring.container.Resolvers.TComponentOwnerResolver
)。在任何版本中,您都需要在
DelegateTo
的内部显式使用nil创建它


如果您正在处理接口上的任何控件,而这些控件放在其他控件(如框架)上通过它们的父属性还请记住,在这种情况下,另一个内存管理机制将发挥作用,如果父组件被破坏,它可能会破坏这样一个组件-如果您只是处理接口表单,这不是一个问题,但我认为我在这里提到它是为了完整性。

请查看并在t中传递所有者他不是零
  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
type
  TInterfacedForm = class(TForm, IInterface)
    // look at System.TInterfacedObject
  end;