PowerBuilder应用开发系列讲座3.docx
- 文档编号:7348699
- 上传时间:2023-01-23
- 格式:DOCX
- 页数:42
- 大小:135.69KB
PowerBuilder应用开发系列讲座3.docx
《PowerBuilder应用开发系列讲座3.docx》由会员分享,可在线阅读,更多相关《PowerBuilder应用开发系列讲座3.docx(42页珍藏版)》请在冰豆网上搜索。
PowerBuilder应用开发系列讲座3
窗体顶端
以下内容含脚本,或可能导致页面不正常的代码
说明:
上面显示的是代码内容。
您可以先检查过代码没问题,或修改之后再运行.
窗体底端
2003-02-2119:
12:
07
窗体顶端
以下内容含脚本,或可能导致页面不正常的代码
说明:
上面显示的是代码内容。
您可以先检查过代码没问题,或修改之后再运行.
窗体底端
第三十二讲:
为下拉式数据窗口建立缓冲区
-------------------------------------------------
为下拉式数据窗口建立缓冲区
在上两期文章中,我们提到了在Master/Detail风格的数据窗口中使用ShareData()函数,可以保持两个数据窗口中数据的一致性。
其实这个函数还有着其他很多不同的用途。
这里我们就另举一例。
许多最终用户在使用PowerBuilder应用程序时抱怨运行速度太慢。
一般来讲,一个企业级的客户/服务器应用程序执行速度的瓶颈并不在于代码执行的效率,而在于应用向后台数据库查询数据时等待后台响应的时间。
改进应用软件速度的关键在于减少应用向后台数据库查询的数据量,减少网络的数据流量,其中减少下拉式数据窗口的查询量就是一个有效的方法。
一般的,为了用户输入方便和避免废键,在数据窗口某些数据列使用下拉式数据窗口是程序员经常采用的方法。
运行一个应用,某一段时间所处理一般都是相同或相近的事务,这样同时打开的不同窗口和数据窗口却很可能同时采用相同的下拉式数据窗口。
在显示这些窗口前,当系统执行主数据窗口的Retrieve()命令时,总是要首先到数据库中查询这些下拉式数据窗口的数据。
如果我们能够减少这些查询,进而减少网络流量,和后台数据库服务器进行语法分析,设计查询算法和执行查询的时间,这将能使应用的性能有较大的提高。
这里我们采用的方法是在客户端建立一个保存结果集的缓冲区,并使用ShareData函数使缓冲区的数据同下拉式数据窗口的主缓冲区建立共享。
我们将这个数据缓冲区建立在一个不可视的窗口上,在这个窗口为每一个不同的结果集创建一个不同的用户对象。
首先我们创建一个标准的不可视的用户对象,在可选的对象类型中选择DataStore,我们并不需要为这个用户对象编写任何代码,只要将其保存为u_dsa即可。
我们创建一个窗口w_resultset_server作为结果集服务器,在这个不可视的窗口中声明这样一些实例变量:
//缓冲区大小
PROTECTEDintegerii_cache_size
//缓冲区
PROTECTEDu_dsaids_cache[]
//我们用以检索结果集的事务对象
PROTECTEDtransactioni_trans
//更新结果集的时间(设为30秒)
PROTECTEDlongil_refresh_interval=1800
//更新的起始时刻
PROTECTEDtimeitm__last_refresh
使用dddw的窗口将通过fw_share_dddw()函数来访问w_resultset_server窗口,这个函数将接受一个数据窗口和一个列名作为参数。
//publicfunctionintegerfw_share_dddw
//参数:
DataWindowadw_parent
//stringas_column_name表现形式为dddw列名
integerli_cache_idx
DataWindowchilddwc
stringls_dataobject_name
//dddw所使用dataobject的名称
ls_dataobject_name=adw_parent.Describe(as_column_name+“.dddw.name”)
IFls_dataobject_name=“”THENRETURN0
//该dataobject是否存在缓冲区中
li_cache_idx=fw_find_dataobject(ls_dataobject_name)
IFli_cache_idx<1THENRETURN0
//同子数据窗口共享数据
adw_parent.GetChild(as_column_name,dwc)
RETURNids_cache[li_cache_idx].ShareData(dwc)
在这个函数中,为确定下拉式数据窗口所使用的数据窗口的名称,首先使用了Describe()函数来获得该列的dddw.name属性。
如果该列名没有找到,或该列的表现形式不是下拉式数据窗口,这个函数的返回值为“”;接下来调用fw_find_dataobject()函数,以确定这个数据结果集是否在缓冲区中,如不存在,就新创建一个;最后使用ShareDate()函数将缓冲区中结果集同下拉式数据窗口共享数据。
这个函数中调用的fw_find_dataobject()函数如下,它接受一个as_dataobject参数,并使用DO...WHILE循环在缓冲区中查找该对象的结果集,如找到将lb_found设为True,否则设为False。
//protectedfunctionintegerfw_find_dataobject
//参数:
stringas_dataobject
integerli_cache_idx=1
booleanlb_found=FALSE
u_dsalds_new_entry
//定位dataobject所在的缓冲区
DOWHILE(NOTlb_found)and(li_cache_idx<=ii_cache_size)
IFids_cache[li_cache_idx].dataobject=as_dataobjectTHEN
lb_found=TRUE
ELSE
li_cache_idx++
ENDIF
LOOP
//如果该dataobject不存在与缓冲区中,则创建一个新入口
IFNOTlb_foundTHEN
IFOpenUserObject(lds_new_entry)<1THEN
RETURN0
ENDIF
lds_new_entry.dataobject=as_dataobject
IFlds_new_entry.SetTransObject(i_trans)<1THEN
RETURN0
ENDIF
IFlds_new_entry.Retrieve()<0THEN
RETURN0
ENDIF
ii_cache_size++
ids_cache[ii_cache_size]=lds_new_entry
li_cache_idx=ii_cache_size
ENDIF
RETURNli_cache_idx
如果该数据对象不存在于缓冲区中,我们将使用OpenUserObject()函数新创建一个用户对象,并将这个DataStore的DataObject属性赋值为as_dataobject,然后调用SetTransObject()函数和Retrieve()函数查询结果。
在这个隐含窗口的Open事件中键入下列代码:
i_trans=sqlca
itm_last_refresh=Now()
//设置起始时间
Timer(60)
在窗口函数fw_find_dataobject()中调用SetTransObject()时使用的事务变量是i_trans,这样做的目的是为了软件更为通用。
我们在Open事件中将这个实例变量赋值为SQLCA,您也可以根据需要给予不同的赋值。
我们使用了一个实例变量itm_last_refresh作为计时器,并且设定每一分钟中断一次,以使窗口根据不同的需要更新缓冲区中的数据。
下面的一个窗口函数fw_refresh_all用以更新缓冲区数据:
//publicsubroutinefw_refresh_all()
integerli_cache_idx
//更新所以缓冲区
FORli_cache_idx=1TOii_cache_size
ids_cache[li_cache_idx].Retrieve()
NEXT
//重新设置更新缓冲区的时间
i_tm_last_refresh=Now()
我们在w_resultset_server的Open事件中对一个计时器进行了初始化,同时还初始化了一个计时变量itm_last_refresh,我们剩下的工作就是在Timer事件中,编写代码根据设定的时间来调用fw_refresh_all()。
timeltm_current_time
integerli_cache_idx
//当前时间
current_time=Now()
//考虑过午夜的特殊情况
IFltm_current_time fw_refresh_all() //检测已过的时间间隔 ELSEIFRelativeTime(itm_last_refresh,ii_refresh_interval) <=ltm_current_timeTHEN fw_refresh_all() ENDIF 一般在一个大型应用中,这个对象中往往要有几十个结果集。 您可能并不希望系统同时更新所有的数据,您可以修改Timer事件中的代码,使系统根据一定的算法,轮流更新缓冲区中的数据,而不使用户感觉到延迟。 值得指出的是,在一般的数据窗口中的dddw,除了在创建时系统会自动对该数据窗口中的所有dddw进行Retrieve()以外,在运行过程中如果没有程序明确指明某个dddw执行Retrieve()函数,系统是不会自动更新其数据的。 因此采用本文推荐的方法还可以保持下拉式数据窗口中的数据接近后台服务器中的最新数据。 如果您在应用中必须使下拉式数据窗口中的数据为后台的最新数据,也可以调用wf_refresh_resultset()强制缓冲区更新数据,使用的参数有两个,数据窗口名称和列名: //publicfunctionbooleanfw_refresh_resultset() //参数: DataWindowadw_parent //stringas_column_name数据窗口中为dddw的列名 integerli_cache_idx stringls_dataobject_name //dddw所使用dataobject的名称 ls_dataobject_name=adw_parent.Describe(as_column_name+“.dddw.name”) IFls_dataobject_name=“”THENRETURNFalse //该dataobject是否存在缓冲区中 li_cache_idx=fw_find_dataobject(ls_dataobject_name) IFli_cache_idx<1THENRETURNFalse //更新缓冲区内的数据 ids_cache[li_cache_idx].Retrieve() RETURNTrue 在这段代码中,我们首先使用fw_find_dataobject函数找到要更新数据的dddw所使用的缓冲区,然后更新该缓冲区的数据即可。 2003-02-2119: 13: 06 wwm 头衔: 真的敌人 等级: 版主 文章: 3405 积分: 7864 门派: 无门无派 注册: 2002年9月11日 第34楼 第三十三讲: 为下拉式数据窗口建立缓冲区(续) --------------------------------------------------------- 为下拉式数据窗口建立缓冲区(续) 同其他4GL工具如Delphi,VisualBasic的早期版本一样,PowerBuilder4.0以前所生成的可执行文件使用是伪代码,也称P-Code(pseudo-code)。 P-Code在运行时是被解释执行的,更准确地说,P-Code使用的是虚拟机指令,为不同的宿主机提供共享的操作命令。 在运行时,操作系统根据不同平台解释实现P-Code指令。 一条P-Code指令可以替代几条机器代码指令,这样就减少了执行代码的大小,不过却以应用的执行效率为代价。 一般的,P-Code的执行速度要慢于编译代码,但文件的大小却小于编译代码。 PowerBuilder5.0引入了生成全编译的可执行代码的功能,以提高运行效率,但同时它也保留了使用P-Code为可执行文件的功能。 使用P-Code的应用程序包括执行文件.EXE和PowerBuilder的动态连接库.PBD,而编译代码所产生的执行文件为.EXE文件和动态连接库DLL。 什么是编译代码 编译代码首先以P-Code为基础,PowerBuilder首先根据P-Code创建C代码,然后将C代码编译成为机器代码的执行文件。 编译后的执行程序中,所有指令都是实际的机器代码。 这就意味着这样的执行文件的大小将远大于P-Code。 使用编译代码仍需要PowerBuilder的运行库,PowerBuilder在执行机器代码时,仍使用共享的函数库,这样做的目的主要是为了节省内存。 使用动态连接库可以避免将所有的功能函数都写在一个可执行文件中,以减小可执行文件的体积。 而在Windows环境中,内存中留有一份DLL的拷贝可以为多个应用程序使用。 此外PowerBuilder5.0还压缩了一些DLL中函数的大小,现在32位平台上运行时只需7个动态连接库,解压缩后为4.5M。 应用所需要的其它DLL如用于数据库访问、分布式PowerBuilder,及RTF编辑器等可在用到时动态地装入。 编译代码创建 编译代码的创建有以下几个步骤: 在开发的过程中,PowerScript首先被翻译成了P-Code,当您在Script编辑器中编写完一个事件或函数的代码返回窗口时,系统就会自动地翻译这一段Script代码。 当您在工程画笔中创建P-Code可执行文件时,PowerBuilder将为不同的PBL中不同对象之间的引用建立起连接,并将这些对象拷贝到指定的EXE或PBD文件中。 这是一个相对较快的过程。 接下来P-Code将被翻译成为C语言的语句。 在这一过程中,工程画笔窗口下面的微帮助中将显示"compiling..."的字样,这一过程约占全部编译时间的10%。 然后是将C代码编译和链接成为机器代码,形成可执行文件和动态连接库,在这一步骤中,微帮助显示的是"generating...",这一编译过程最费时间,将占约90%的编译时间。 通过上面的介绍,我们看到创建机器代码所用的时间比产生P-Code的用时要多得多,因为后者只是一个二进制代码搬运的过程。 因此在开发过程中,我们一般使用的主要是P-Code,只是在最终交付用户使用时,才根据实际情况选择是否创建机器代码。 编译代码的优势: 在以下这几个方面,将PowerScript代码编译成为机器代码将得到较快的运行速度: 循环结构 浮点运算 整数运算 函数调用 但是在另外的一些方面,编译成为机器代码并不能使运行速度明显加快,如涉及图形用户界面,数据库访问,小数运算,字符串操作等。 在有些情况下,两种代码的速度是相同的,如对资源的调用和对数据窗口的执行。 在这些情况下,您就无法通过使用编译代码来提高运行的速度了。 如果您的应用是以执行自身的代码为主,例如应用中较多的是同一条代码被反复执行(如循环)或是编写的代码主要用来进行数学运算,这样的应用应当使用编译代码。 在函数调用方面,使用机器码也要比P-Code快得多。 因此如果您的Script大量的调用函数或是采用新的语法形式调用事件,使用机器码也将是个好的选择。 不过您应当记住,编译代码的执行文件大小要比P-Code大得多,因为一条PowerScript代码将有可能编译成为5条甚至10条C代码。 当这些C代码被编译后,可执行的代码将远远大于相应的P-Code,因此如果您的应用程序的文件大小是您应用的首要考虑因素,或者您的应用较多的是数据库访问,那您应当选择使用P-Code。 提高应用的性能 事实上,一个好的数据库的物理设计和应用程序的模块设计可
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- PowerBuilder 应用 开发 系列 讲座
![提示](https://static.bdocx.com/images/bang_tan.gif)