我有一个窗体文件,被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窗体调用数据模块的所有代码后问题依旧,检查了所创建的对象,没有没释放的,现在查不出原因,还望各位帮忙。
另有一个是本地数据模块窗体,也封装进了一个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窗体调用数据模块的所有代码后问题依旧,检查了所创建的对象,没有没释放的,现在查不出原因,还望各位帮忙。
没有仔细看,不过你的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;------------------------------------------------------