关于Delphi7自带的Pool例子 ( 积分: 100 )

  • 主题发起人 Duringwind
  • 开始时间
D

Duringwind

Unregistered / Unconfirmed
GUEST, unregistred user!
Delphi7中自带的Pool例子,在类型库中手工创建了两个类TPoolRDM和TPool,不是很明白这两个类在这里起的作用,还请各位帮忙解释一下。谢谢。
 
一个是池类,一个远端
 
我指的是在类型库文件里面的那两个,其实我把类型库里面的这两个类删除了也不影响程序的运行。所以我不太清楚为什么需要在类型库中手工添加这两个类,而且名字和其他文件的重复。
 
调用时,先调用池类,再通过池类来调用远端
 
你注意看Server_TLB文件了吗?这个TLB和一般用类型库编辑器产生的不太一样!!
PooledRDM,Pooler都是从IPooledRDM接口继承,PooledRDM是类型库编辑器自动产生的,Pooler要手动加入!!

还有:
TPooler是ciMultiInstance, tmFree的,也就是它可以多实例多线程模式。

TPooledRDM是ciInternal, tmApartment的,说明它是内部的,单线程的模式。
 
奇怪,我的表达能力难道这么差?我指的是server_tlb.pas文件中这个部分的代码:
Line 102--Line 142
/ *********************************************************************//
// OLE Server Proxy class declaration
// Server Object : TPooledRDM
// Help String : CoClass for the RDM that is to be pooled.
// Default Interface: IPooledRDM
// Def. Intf. DISP? : No
// Event Interface:
// TypeFlags : (2) CanCreate
// *********************************************************************//
TPooledRDM = class(TOleServer)
private
FIntf: IPooledRDM;
function GetDefaultInterface: IPooledRDM;
protected
procedure InitServerData;
override;
public
procedure Connect;
override;
procedure Disconnect;
override;
// --------------
// --------------
function AS_ApplyUpdates(const ProviderName: WideString;
Delta: OleVariant;
MaxErrors: Integer;
out ErrorCount: Integer;
var OwnerData: OleVariant): OleVariant;
function AS_GetRecords(const ProviderName: WideString;
Count: Integer;
out RecsOut: Integer;
Options: Integer;
const CommandText: WideString;
var Params: OleVariant;
var OwnerData: OleVariant): OleVariant;
function AS_DataRequest(const ProviderName: WideString;
Data: OleVariant): OleVariant;
function AS_GetProviderNames: OleVariant;
function AS_GetParams(const ProviderName: WideString;
var OwnerData: OleVariant): OleVariant;
function AS_RowRequest(const ProviderName: WideString;
Row: OleVariant;
RequestType: Integer;
var OwnerData: OleVariant): OleVariant;
procedure AS_Execute(const ProviderName: WideString;
const CommandText: WideString;
var Params: OleVariant;
var OwnerData: OleVariant);
// --------------
property DefaultInterface: IPooledRDM read GetDefaultInterface;
// --------------
// --------------
// --------------
// --------------
published
end;

Line 157--Line 197
// *********************************************************************//
// OLE Server Proxy class declaration
// Server Object : TPooler
// Help String : CoClass for the pooler object.
// Default Interface: IPooledRDM
// Def. Intf. DISP? : No
// Event Interface:
// TypeFlags : (2) CanCreate
// *********************************************************************//
TPooler = class(TOleServer)
private
FIntf: IPooledRDM;
function GetDefaultInterface: IPooledRDM;
protected
procedure InitServerData;
override;
public
procedure Connect;
override;
procedure Disconnect;
override;
// --------------
// --------------
function AS_ApplyUpdates(const ProviderName: WideString;
Delta: OleVariant;
MaxErrors: Integer;
out ErrorCount: Integer;
var OwnerData: OleVariant): OleVariant;
function AS_GetRecords(const ProviderName: WideString;
Count: Integer;
out RecsOut: Integer;
Options: Integer;
const CommandText: WideString;
var Params: OleVariant;
var OwnerData: OleVariant): OleVariant;
function AS_DataRequest(const ProviderName: WideString;
Data: OleVariant): OleVariant;
function AS_GetProviderNames: OleVariant;
function AS_GetParams(const ProviderName: WideString;
var OwnerData: OleVariant): OleVariant;
function AS_RowRequest(const ProviderName: WideString;
Row: OleVariant;
RequestType: Integer;
var OwnerData: OleVariant): OleVariant;
procedure AS_Execute(const ProviderName: WideString;
const CommandText: WideString;
var Params: OleVariant;
var OwnerData: OleVariant);
// --------------
property DefaultInterface: IPooledRDM read GetDefaultInterface;
// --------------
// --------------
// --------------
// --------------
published
end;

这两个类应该都是手工增加的吧?没有那个是自动产生的,我新建一个RDM,检查了类型库文件中,没有类似继承TOleServer的代码。我不明白的是这里,而不是Pooler.pas和srvdm.pas中的两个类。
 
我才明白,没有类似继承TOleServer的代码是因为你的作法不对!
应该先建一个ActiveX项目,然后在这个项目中放入一个远程数据模块,就会产生Pooler原示例的类似代码!
 
ciMultiInstance, tmFree,ciInternal, tmApartment这些你搞清楚了吗?没搞清楚的话,先看一下COM的基础知识。
看样子,你是没搞过三层。哪怕李维说的哪种伪三层。想看懂Pooler例子要先有COM基础。
 
TPooledRDM和TPooler它们都是IPooledRDM接口的类实例,它并不是一般的类。它们是COM接口的类实例;它们是为IPooledRDM接口而存在的。
TPooledRDM的作用是创建一个内部的,单线程的远程数据模块,它由TPoolManager调用,用于生成指定池容量的远程数据模块。然后放入TPoolManager内部的池中。
TPooler的作用是一个代理,它实际用途是为了让客户端调用,它是多实例,多线程的,用于满足多个客户端调用。
 
gencheng,先谢谢了。
//////////////////
TPooledRDM和TPooler它们都是IPooledRDM接口的类实例,它并不是一般的类。它们是COM接口的类实例;它们是为IPooledRDM接口而存在的。
TPooledRDM的作用是创建一个内部的,单线程的远程数据模块,它由TPoolManager调用,用于生成指定池容量的远程数据模块。然后放入TPoolManager内部的池中。
TPooler的作用是一个代理,它实际用途是为了让客户端调用,它是多实例,多线程的,用于满足多个客户端调用。
///////////////////
上面这部分我都明白。
/////////////////////
应该先建一个ActiveX项目,然后在这个项目中放入一个远程数据模块,就会产生Pooler原示例的类似代码!
///////////////////
这部分我试过了,找不到类似TPooledRDM = class(TOleServer)这样的代码,我用的是d7,晚上回去再试试看。
 
“TPooledRDM = class(TOleServer)”
你为什么一定要这样??? 如果真的这样了,你创建的远程模块接口IPooledRDM接口还有什么意义?不知你明白了没有?
你能出现“TPooledRDM = class(TOleServer)”这种疑问,说明你还是没真正理解这个连接池Pooler示例的意义。。。
其实不一定非得要创建一个远程模块接口IPooledRDM,Borland的这个Pooler示例是因为要使用Midas的两种(Socket和DCOM)连接方式才创建远程数据模块接口IPooledRDM,如果你使用是COM(COM+方式)连接,就不需要创建远程数据模块,使用一般的数据模块就可以了,甚至可以不创建数据模块。
 
我也是才学COM不到一个月,近期这个Pooler研究了快一个星期。对于这个Pooler的整体框架基本搞清楚了。当然还有一些细节没搞明白,现在正在努力中。。。
希望大家共同讨论这个示例。共同学习,共同提高。
 
-----“TPooledRDM = class(TOleServer)”
-------你为什么一定要这样???
不是我一定要这样,而是pooler例子中有这样的语句,我不明白为什么会出现这样的语句,所以才来问问。
TPooler-Tpoolmanager-TpooledRdm这三者的关系我是明白的。
 
我被楼上搞糊涂了。。。
我的Pooler示例中没有你上面写的代码。我的TPooldeRDM是这样定义的:
TPooledRDM = class(TRemoteDataModule, IPooledRDM)
Session1: TSession;
Database1: TDatabase;
。。。。。。
。。。。。。
如果TPooledRDM中没有继承IPooledRDM,那么它将毫无用处!!!
我用的是Delphi7企业版,应该只有一种Delphi7企业版吧!
更搞不清楚的是楼主声称在server_tlb.pas文件中有TPooledRDM,TPooler的类定义,真是奇谈!tlb是干什么的,楼主你搞清楚了吗?tlb文件中是不能有private
,protected域的,如果有,那么它违反了COM规范,别的语言也就没法重用这个com组件了。
把你的Pooler示例发过来,我看一下,和我的有什么不同?
我的邮箱: gencheng@tom.com

 
发给你了,应该是版本不同。
 
果然不同!发个我的这个版本的server_tlb.pas文件程序源码:
unit Server_TLB;
// ************************************************************************ //
// WARNING
// -------
// The types declared in this file were generated from data read from a
// Type Library. If this type library is explicitly or indirectly (via
// another type library referring to this type library) re-imported, or the
// 'Refresh' command of the Type Library Editor activated while editing the
// Type Library, the contents of this file will be regenerated and all
// manual modifications will be lost.
// ************************************************************************ //
// PASTLWTR : 1.2
// File generated on 2007-11-24 12:50:47 from Type Library described below.
// ************************************************************************ //
// Type Lib: D:/Pooler/Server.tlb (1)
// LIBID: {0CE99800-9F28-11D1-8944-00A0248E5091}
// LCID: 0
// Helpfile:
// HelpString: Server Library
// DepndLst:
// (1) v1.0 Midas, (C:/WINDOWS/system32/midas.dll)
// (2) v2.0 stdole, (C:/WINDOWS/system32/Stdole2.tlb)
// ************************************************************************ //
{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers.
{$WARN SYMBOL_PLATFORM OFF}
{$WRITEABLECONST ON}
{$VARPROPSETTER ON}
interface
uses Windows, ActiveX, Classes, Graphics, Midas, StdVCL, Variants;

// *********************************************************************//
// GUIDS declared in the TypeLibrary. Following prefixes are used:
// Type Libraries : LIBID_xxxx
// CoClasses : CLASS_xxxx
// DISPInterfaces : DIID_xxxx
// Non-DISP interfaces: IID_xxxx
// *********************************************************************//
const
// TypeLibrary Major and minor versions
ServerMajorVersion = 1;
ServerMinorVersion = 0;
LIBID_Server: TGUID = '{0CE99800-9F28-11D1-8944-00A0248E5091}';
IID_IPooledRDM: TGUID = '{0CE99801-9F28-11D1-8944-00A0248E5091}';
CLASS_PooledRDM: TGUID = '{0CE99802-9F28-11D1-8944-00A0248E5091}';
CLASS_Pooler: TGUID = '{0CE99804-9F28-11D1-8944-00A0248E5091}';
type
// *********************************************************************//
// Forward declaration of types defined in TypeLibrary
// *********************************************************************//
IPooledRDM = interface;
IPooledRDMDisp = dispinterface;
// *********************************************************************//
// Declaration of CoClasses defined in Type Library
// (NOTE: Here we map each CoClass to its Default Interface)
// *********************************************************************//
PooledRDM = IPooledRDM;
Pooler = IPooledRDM;

// *********************************************************************//
// Interface: IPooledRDM
// Flags: (4432) Hidden Dual OleAutomation Dispatchable
// GUID: {0CE99801-9F28-11D1-8944-00A0248E5091}
// *********************************************************************//
IPooledRDM = interface(IAppServer)
['{0CE99801-9F28-11D1-8944-00A0248E5091}']
end;

// *********************************************************************//
// DispIntf: IPooledRDMDisp
// Flags: (4432) Hidden Dual OleAutomation Dispatchable
// GUID: {0CE99801-9F28-11D1-8944-00A0248E5091}
// *********************************************************************//
IPooledRDMDisp = dispinterface
['{0CE99801-9F28-11D1-8944-00A0248E5091}']
function AS_ApplyUpdates(const ProviderName: WideString;
Delta: OleVariant;
MaxErrors: Integer;
out ErrorCount: Integer;
var OwnerData: OleVariant): OleVariant;
dispid 20000000;
function AS_GetRecords(const ProviderName: WideString;
Count: Integer;
out RecsOut: Integer;
Options: Integer;
const CommandText: WideString;
var Params: OleVariant;
var OwnerData: OleVariant): OleVariant;
dispid 20000001;
function AS_DataRequest(const ProviderName: WideString;
Data: OleVariant): OleVariant;
dispid 20000002;
function AS_GetProviderNames: OleVariant;
dispid 20000003;
function AS_GetParams(const ProviderName: WideString;
var OwnerData: OleVariant): OleVariant;
dispid 20000004;
function AS_RowRequest(const ProviderName: WideString;
Row: OleVariant;
RequestType: Integer;
var OwnerData: OleVariant): OleVariant;
dispid 20000005;
procedure AS_Execute(const ProviderName: WideString;
const CommandText: WideString;
var Params: OleVariant;
var OwnerData: OleVariant);
dispid 20000006;
end;

// *********************************************************************//
// The Class CoPooledRDM provides a Create and CreateRemote method to
// create instances of the default interface IPooledRDM exposed by
// the CoClass PooledRDM. The functions are intended to be used by
// clients wishing to automate the CoClass objects exposed by the
// server of this typelibrary.
// *********************************************************************//
CoPooledRDM = class
class function Create: IPooledRDM;
class function CreateRemote(const MachineName: string): IPooledRDM;
end;

// *********************************************************************//
// The Class CoPooler provides a Create and CreateRemote method to
// create instances of the default interface IPooledRDM exposed by
// the CoClass Pooler. The functions are intended to be used by
// clients wishing to automate the CoClass objects exposed by the
// server of this typelibrary.
// *********************************************************************//
CoPooler = class
class function Create: IPooledRDM;
class function CreateRemote(const MachineName: string): IPooledRDM;
end;

implementation
uses ComObj;
class function CoPooledRDM.Create: IPooledRDM;
begin
Result := CreateComObject(CLASS_PooledRDM) as IPooledRDM;
end;

class function CoPooledRDM.CreateRemote(const MachineName: string): IPooledRDM;
begin
Result := CreateRemoteComObject(MachineName, CLASS_PooledRDM) as IPooledRDM;
end;

class function CoPooler.Create: IPooledRDM;
begin
Result := CreateComObject(CLASS_Pooler) as IPooledRDM;
end;

class function CoPooler.CreateRemote(const MachineName: string): IPooledRDM;
begin
Result := CreateRemoteComObject(MachineName, CLASS_Pooler) as IPooledRDM;
end;

end.

今天白天看《Delphi COM深入编程》也好像有你的哪样的代码,现在正在看。
好像咱们的这两个版本之间就是server_tlb.pas部分不完全相同。其它的文件好像完全一样。
TLB文件是类型文件,它是给其它语言的开发工具准备的。它是系统自动生成的,为什么有这样差别我也不清楚,但可以肯定的是,它并不是作者手写的,它是系统自动生成的。所以,我认为其它的文件,像pooler,srvrdm等等才是这个Pooler的重点,也是我们应该关心的。
我给你发一个我的版本的Pooler你参考一下。
 
刚才将你的server_tlb.pas文件替换了我的这个Pooler,发现它完成的功能和我的这个完全一样,并不影响功能。我想可能是生成tlb文件的时候有哪个选项不同吧。
所以,我更加肯定了server_tlb.pas文件不是这个Pooler程序的重点。
 
今晚做好了ADO + SQL server 2000 + COM+连接池。
测试:
在本机上打开了60个客户端,随机选择60个客户端中的任意一个,测试都可以完成相应客户端的全部功能。测试通过!
而我明白的知道,因为我自己在本机上无论如何也无法做到任一时刻“同时”用到2个客户端数据库连接,因为每次同数据库连接并返回数据只用0.0x秒时间,并且因为用了数据库连接池,事实上,这60个客户端只共享了1个连接好的数据库连接,也就是说:比如我设置了连接池的最大连接数为15个,我现在打开的这60个客户端只用到了数据库连接池的十五分之一!
数据库连接池真是很强大!!
 
顶部