我有一个窗体文件,被uses进了一个dll工程序中,这个窗体类还实现了一个接口,其实也就是想通过接口让应该程序来调用这个窗体。
另有一个是本地数据模块窗体,也封装进了一个DLL文件中,与上面类同,也让这个数据模块窗体类实现了一个接口,也想让应用程序通过接口来创建和使用这个数据模块上的资源。我现在有一个应该程序,启动后先创建了一个COM+组 件,然后又创建了数据模块窗体。然后点应该程序上的一个按钮来创建调用封在DLL中窗体,窗体创建时装COM+组件接口传进去,将数据模块接口传进去,窗体创建后会将一个私有的TClientdataset变量传入数据模块上,将数据模块上的一个数据集赋值给这个变量,也就是说上窗体上的一个数据集直接访问模块上的数据集(这样好象很不安全,但只作只读操作,用完后就将这个变量置空了),将关闭这个窗体,再关闭应该程序后,窗体都消失了,但应用程序仍然在内存中。不知为什么!简单代码如下窗体
  IEmployee=interface(IInterface)
    GUID;
    procedure showfrm;
  end;  TForm1=class(TForm,IEmployee)  public
    constructor create(Ahandle:THandle,mts:IUnknown,DM:IDM );
    procedure showfrm;
  end;数据模块
  IDM = interface(IUnknown)
    ['{25BFFFA1-AD7E-4C8E-B3FB-2E8C2DFD91E4}']
    procedure DownData(const Aeid,ADataType: integer; Mts: IUnKnown);    procedure GetDataSet(var ACDS: TClientDataSet;ADataType: Integer);
    function GetData(ADataType: Integer): OleVariant;  end;TDM = class(TDataModule,IDM)
public
  constructor Create(AOwner: TComponent;Auid: integer);  procedure DownData(const Aeid,ADataType: integer; Mts: IUnKnown);  procedure GetDataSet(var ACDS: TClientDataSet;ADataType: Integer);  function GetData(ADataType: Integer): OleVariant;
end;
应用程序procedure Ttest.FormCreate(Sender: TObject);
begin
  mts:=CreateRemoteComObject('192.168.0.16', CLASS_OA) as IunKnown;
  dm:=CreateDM(Application.Handle,6,Application);<<<这个函数是数据模块DLL中的返回IDM接口
end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  mts:=nil;
  dm:=nil;
end;procedure Ttest.Button1Click(Sender: TObject);
begin
  Frm:= CreateEmployeeArchives(application.Handle,mts,dm,fa,nil);<<这是窗体DLL中的函数,返回IEmployee接口
end;当调用完子窗体后关闭应用程序,应用程序无法正常关闭,没有任何错误提示,但Delphi中的编译器上的绿色三角为灰色,就是不结束,好象有资源泄漏了,我屏蔽了DLL窗体调用数据模块的所有代码后问题依旧,检查了所创建的对象,没有没释放的,现在查不出原因,还望各位帮忙。

解决方案 »

  1.   


    没有仔细看,不过你的IEmployee,IDM引用的对象最后都没有释放.你是这样实现,但这样有问题,就是接口引用计数处理上.
    TForm1=class(TForm,IEmployee)
    TDM = class(TDataModule,IDM)TForm和TDataModule都是从TComponent继承下来的,
    在TComponent里面实现的IInterface接口,因些在编程你代码时候不会报错.
    但问题是这儿,TComponent处理IInterface不会设计成没有引用计数就自动释放的. ----------看得出来,这儿引用计数为0时候也不会释放对象--------------------
    function TComponent._Release: Integer;
    begin
      if FVCLComObject = nil then
        Result := -1   // -1 indicates no reference counting is taking place
      else
        Result := IVCLComObject(FVCLComObject)._Release;
    end;---------------------------------------------------------------------因为照你的思路,应该自己处理引用计数,
    TXMLDocument这个组件的实现你可以参考一下..它就实现了自动释放.-------------------------------------------------------
      TXMLDocument = class(TComponent, IInterface, IXMLDocument, IXMLDocumentAccess)
    ....
        { IInterface }
        function _AddRef: Integer; stdcall;
        function _Release: Integer; stdcall;
    ......-------------------------------------------------------
    function TXMLDocument._Release: Integer;
    begin
      Result := InterlockedDecrement(FRefCount);
      { If we are not being used as a TComponent, then use refcount to manage our
        lifetime as with TInterfacedObject. }
      if (Result = 0) and not FOwnerIsComponent then
        Destroy;//释放自已..
    end;------------------------------------------------------