打印本文 打印本文 关闭窗口 关闭窗口
《关于VisiBroker For Delphi的使用》(4)
作者:武汉SEO闵涛  文章来源:敏韬网  点击数4305  更新时间:2009/4/23 18:44:55  文章录入:mintao  责任编辑:mintao
LibCRB_s,


  StdCtrls;


 


type


  TForm1 = class(TForm)


      procedure FormCreate(Sender: TObject);


  private


  { private declarations }


  protected


  { protected declarations }


  


MyCRB:InterfaceCRB;


    procedure InitCorba;


  public


  { public declarations }


  end;


 


var


  Form1: TForm1;


 


implementation


 


{$R *.DFM}


 


procedure TForm1.InitCorba;


begin


  CorbaInitialize;


  MyCRB:=TInterfaceCRBSkeleton.Create(''''MyCRBServer'''',TInterfaceCRB.Create);


  BOA.ObjIsReady(MyCRB as _Object);//CORBA服务就绪


end;


 


procedure TForm1.FormCreate(Sender: TObject);


begin


  InitCorba;//初始化调入


end;


 


end.


/******************************************************/


/客户端程序


nit UnClientMain;


 


interface


 


uses


  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,


  Corba, TypeLibCRB_c, TypeLibCRB_i, Grids, DBGrids, DB, DBClient, StdCtrls;


 


type


  TForm2 = class(TForm)


    Edit1: TEdit;


    Button1: TButton;


    ClientDataSet1: TClientDataSet;


    DataSource1: TDataSource;


    DBGrid1: TDBGrid;


    procedure Button1Click(Sender: TObject);


    procedure FormCreate(Sender: TObject);


  private


  { private declarations }


  protected


    /    myCRB:InterfaceCRB;


 


  { protected declarations }


  public


  { public declarations }


  end;


 


var


  Form2: TForm2;


 


implementation


 


{$R *.DFM}


 


 


 


procedure TForm2.Button1Click(Sender: TObject);


begin


 ClientDataSet1.Data:=myCRB.GetSQLData(Edit1.Text,false);


end;


 


procedure TForm2.FormCreate(Sender: TObject);


begin


  myCRB:=TInterfaceCRBHelper.Bind(''''MyCRBServer'''',''''127.0.0.1'''');


end;


 


end.


上面的程序让你无法使用ApplyUpdate方法来从客户端更新数据,如果要更新数据必须通过GetSQLData(SQL,True)来更新数据,相对来说客户端将不能使用数据感知类组件来编写插入删除,修改类程序,因为你的中间层的数据集与数据提供者不具有持久性,这就是下面代码使用DMPooler的精妙之处。


//


  TDataModuleClass = class of TDataModule; // "class" reference


首先,由于客户请求数目的不确定性,我们必须为可能的请求提供一个用于存放独立实例请求单元的空间量(Pooler Size),假定我们考虑的可能有5个独立请求同时拥有这样持久对象,那么我们可以设定PoolSize=5,注意必须定义在全局的CONST中,因为每个对象是一个独立体,不过里也可以将这样的对象列入到TLIST对象中保存,当然还有更高级的构造方式,这些东西来源于程序员对Delphi的理解程度,例如:你可以将全部的实例使用TCollection类化处理,而不是使用下面的记录类型:


  TPooledModule = record


    Module: TDataModule;


InUse: Boolean;       


end;


当然这个地方使用的比较基础的方式来处理每一个ITEM,这个单元中包含了一个TDataModule实例,何一个表示这个实例是否被起用的开关量(我是这么命名的,当然这仅是基本的表达,而根据业务需求的规则需要自己来定义比此更好的比编写方式,而这个东西同样来源于对于OO概念的理解,和面向对象编程的经验的积累).


当然,由于我们的客户对象的相互独立并确是一个持久的对象,那么也就是告诉我们整个对象池,是一个多线程的架构(如果是初次接触的朋友们最好先去读一下Thread).所以我们必须在对象的构造方法中申明为


constructor TModulePooler.Create;


begin


  IsMultiThread := True;


……


end;


如果请求被客户中断,或则实例由于异常而停止我们必须将这个实例终止,释放实例对象:


procedure TModulePooler.FreeModule(DataModule: TDataModule);


var


  I: Integer;


Begin


………


    for I := 0 to Length(FModules) - 1 do


      if FModules[I].Module = DataModule then


        FModules[I].InUse := False;


ReleaseSemaphore(FSemaphore, 1, nil);


……..


end;


那么,创建和释放的方法在我们写好已后,那么我们如何来构造这个单元的实体方法呢?


请看:


function TModulePooler.GetModule: TDataModule;


var


  I: Integer;


begin


  Result := nil;


  if WaitForSingleObject(FSemaphore, 5000) = WAIT_TIMEOUT then


//设定延时响应,假定服务超时,那么我们将引发一个异常类,表示服务器太忙而未能响应请求。


    raise Exception.Create(''''Server too busy'''');


  try


if Length(FModules) = 0 then


//如果这个对象记录数组为空我们将创建这样一个动态的对象记录数组,即创建一个链表,每个对象作为其中的一个单元而存在,当然在实际的开发中我认为这种方法不是最好的,我会采用TStrings或则Tlist以及TCollections来存放单元,具体的使用我会在下一节给出


    begin


      SetLength(FModules, PoolSize);


      for I := 0 to PoolSize - 1 do


        begin


          FModules[I].InUse := False;


          FModules[I].Module := FModuleClass.Create(Application);


        end;


    end;


    for I := 0 to Length(FModules) - 1 do


      if not FModules[I].InUse then


      begin


        FModules[I].InUse := True;


        Result := FModules[I].Module;


        Break;


      end;


  finally


    FCSect.Leave;


  end;


  //Check if we ran out of connections


  if not Assigned(Result) then


    raise Exception.Create(''''Pool is out of capacity'''');


end;


在加载时创建


initialization


  ModulePooler := TModulePooler.Create;


退出时释放


finalization


  ModulePooler.Free;


千万要记住检测对象是否存在,一定要在不再使用的时候释放持久对象,否则就会不断的堆砌,最终溢出哦!


可能是工作的原因,最近总是抽不出太多的时间来写这样的文章,在我看来已后基于C/S的软件将会越来越少,而绝大多数会聚集于微软的COM+体系中,这倒不是

上一页  [1] [2] [3]  下一页

打印本文 打印本文 关闭窗口 关闭窗口