认识VF--Visual FoxPro 漫谈
2007-11-11 11:37:25 来源:WEB开发网
简介
性能总是Microsoft® FoxPro®数据库管理系统的主要特点之一,尤其是在数据库引擎方面。在介绍了Microsoft Visual FoxPro™有关的数据库开发系统以及它相关的对象模型,加强引擎,还有客户端/服务器特性之后,你就会发现整个产品的功能变得越来越强大了。然而强大的另一面就是产品也变得越来越复杂了。因此,当开发越来越强劲时,面向对象的应用程序使用远程数据存储器中的数据变得越来越容易了,同时,应用程序也变得更加慢了。
本文要为你介绍一些实践技巧和技术,帮助你改善你的应用程序的性能。只要你在应用程序中正确的使用了这些技术,你就能够明显改善你的用户界面和数据访问性能。
尽管应用起来只有部分技巧结果比较明显,我们还是希望我们所介绍的能够给你提供有用的信息,帮助你全面改善应用程序的性能。同时,我们希望你能够把你的意见或经验反馈给我们,这样今后使用Visual FoxPro的开发者要提高应用程序的性能时就能获得更多的帮助,这正如你的前人所做的一样。
硬件配置
在这一部分我们将介绍调整操作系统的技巧,经过调整之后操作系统将会与Visual FoxPro一起工作得更加和谐。在某些情况下你需要改变硬盘缓存器的值以达到优化性能,从而满足应用程序需要的目的。
Microsoft Windows 95 和Windows NT
在大多数情况下Microsoft Windows® 95和 Windows NT®操作系统与Visual FoxPro一起工作得非常好。唯一的例外就是在Windows NT Server上运行Visual FoxPro。因为Windows NT Server 需要的内存比Visual FoxPro想象的还多,所以Visual FoxPro只能够为自己超支分配内存使用。
为了解决这种情况,你可以用SYS(3050)系统函数来调整Visual FoxPro的内存缓冲区,把它近似调整为它的缺省值的三分之一(详情见内存管理)。例如,你可以把下面这一行代码添加到启动编码或者是CONFIG.FPW文件中去:
=SYS (3050, VAL (SYS (3050, 1, 0)) / 3)
本地数据性能
Rushmore 和索引
在MSDN Library的Visual FoxPro Developer's Guide中,第十五章“优化应用程序”一文详细地讨论了Rushmore™技术。下面再补充说明一些技巧。
使用索引
使用索引能够提高数据查询的性能,这是很明显的。在Visual FoxPro中,索引是树形的数据结构,所以在索引中查询非常快。
Visual FoxPro最独特的方面之一就是支持在索引中使用公式。大多数数据库管理系统(DBMSs)允许使用一个或更多个字段进行查询,而Visual FoxPro允许在索引中使用任何公式,甚至是用户自定义的函数。
不过你要注意的是,当你往表格中添加了很多的索引时,更新和插入速度会比较慢,因为此时Visual FoxPro要更新每一个索引。通常,你只需要为那些在过滤器和汇合指令中使用的数据建立索引。
你要避免使用FOR <条件 > 或者NOT <条件 >形式的索引公式,因为这些公式对于索引来说是不可优化的。例如:
INDEX ON DELETED() TAG DEL
是Rushmore可优化的,但是
INDEX ON NOT DELETED()TAG NOTDEL
不是。作为一个查询的特殊情况,当你不想删掉记录时,如果你已经SET DELETED ON,那么使用第一个例子中的索引公式会帮助你加快操作速度。
如果你在公式中使用了一个FOR的句子,Visual FoxPro不会使用索引来达到最优化。例如
INDEX ON ORDNUM FOR DISCOUNT > 10 TAG ORDDISC
最后,注意不要使用那些只能用离散值的索引(如逻辑字段等)。
何时进行查询Rushmore优化?
什么时候对Visual FoxPro表格进行的查询或者过滤要用Rushmore优化,以及什么时候只是需要部分地进行优化,这些问题都很重要。
Visual FoxPro用Rushmore技术来优化过滤条件,它会找寻符合过滤器左边表达式的索引关键表达式。通常,开发者们会错误地试图把一个索引的标记名与一个过滤器的表达式的相匹配,这样只会发现Visual FoxPro不能够用这种方法进行优化。以下是一个错误地使用了索引的例子:
USE CUSTOMER
INDEX ON UPPER(contact) TAG name
SELECT * FROM customer ;
WHERE contact="BILL" && not optimized. No index on "contact"
以下是在过滤查询中正确利用索引的方法:
SELECT * FROM customer WHERE UPPER(contact)="BILL" && Optimized!
你还可以用SYS(3054)函数来决定Rushmore查询优化的等级。SYS(3054)可以显示也可以不显示查询的Rushmore优化等级。SYS(3054,1)表示显示Rushmore 优化的等级,而SYS(3054,0) 则表示不显示Rushmore优化的等级。
数据库引擎性能特性
主索引和侯选的索引
在FoxPro 2.x中,用唯一的ID号来增加记录的典型技术就是在你的关键字段中建立一个索引,要增加记录时就运行一个搜索程序来查看这个ID号是否已经被使用了。虽然这个方法已经比较快了,但是它还不是最理想的。
用Prima(最完善的虚拟主机管理系统)ry 和Candidate关键字插入(或者更新)Visual FoxPro表格中,这种方法是由数据库引擎验证的唯一方法,它用于比较低的级别中,速度非常快。
用可区别的标记来提高性能
在Visual FoxPro中,我们改进了查找具有通用特征(指那些有可区别标记的特征)的数据的方法。如果你的索引表达式的结果不支持可区别的标记(如B或M),查找会快一些。
Non-Machine比较顺序
non-Machine比较顺序(如General)比Machine比较顺序慢的原因有两点:
Non-Machine的索引关键字比Machine的索引关键字长一倍,因为它们要包含可区别的信息。
Non-Machine比较用了许多特别的规则来为特征值建立索引,这样它才能返回正确的结果。
因为Machine比较顺序相对来说要快一些,所以它通常用于连接和查找,而其他的比较顺序通常用来为记录排序。
注意:Visual FoxPro利用的索引仅仅是用SET COLLATE当前的设置来建立的。因此,典型的解决方法是在主要的搜索和分类字段中有两个索引:
SET COLLATE TO "GENERAL"
INDEX ON lastname TAG lastname && sort index
SET COLLATE TO "MACHINE"
INDEX ON lastname TAG _lastname && seek/select index
如果你想要用相对来说比较快的Machine索引来对字段进行查找,选择或者连接,请在进行之前使用SET COLLATE TO "MACHINE"。Rushmore会使用在Machine比较顺序中建立的索引,查找和选择/连接都非常快。
用SQL SELECT
如果在Machine比较顺序中完成了一个SQL SELECT,那么任何ORDER BY 或者GROUP BY都可以用Machine比较顺序。如果你要用non-Machine比较顺序为结果记录排序,你可以在这个比较顺序中完成SELECT,当然这样做比较慢,也可以分两步把它完成:
第一步:用"Machine"比较顺序来选择记录。
SET COLLATE TO "MACHINE" && use only 'machine' indexes
SELECT * FROM table INTO CURSOR temp1 WHERE lastname = "Müller"
第二步:用"General"比较顺序为记录排序。
SET COLLATE TO "GENERAL" && use only 'general' indexes
SELECT * FROM temp1 INTO TABLE output ORDER BY lastname
新数据类型
我们在Visual FoxPro中引进了几个新的数据类型:DateTime, Integer, Double, 和Currency。所有这些类型的数据在硬盘上将存为二进制数据(其中Integer是一个四个字节的二进制值,其他的是八个字节的二进制值)。
这样做有两个优点。第一个优点是,因为存储在硬盘上的数据量比较小(一个八位的数作为Numeric来存储要占八个字节,而作为Integer来存储则只要四个字节),所以从硬盘往内存里调数据和索引时,一次能够调更多的数据到内存页中去,这样速度就会比较快一些。第二个优点是,无须进行数据的传送。在内部,如果Visual FoxPro把整数看作四个字节的二进制值,那么需要把它转换为数字才能以ASCII码数据的形式存储在硬盘中。因而,每一次读取数据都必须先从ASCII码转换成为二进制,然后再转换回去。有了Integers, Doubles, DateTimes, 和Currency几种数据类型,这种转换就不必要了,对数据的访问自然就快了很多。
在新的数据类型中,Integer对速度的影响最大。因此,只要有可能,尽量地把主要的和外来的关键值设置为Integer。好处就是:.DBF文件更小了,索引更小了,而连接就更快了(这也许才是最重要的)。
缓冲和事务处理
事务处理必须简短。看看下面这个例子:
BEGIN TRANSACTION
DO FORM BIGFORM TO nResult
IF nResult = IDCOMMIT
END TRANSACTION
ELSE
ROLLBACK
ENDIF
上面这个例子说明了什么?如果你认为这是一个操作的恰当的事务处理的封装,的确如此。但是,事务处理仅仅用于限制数据的更新。如果你做的不仅仅是这些(如涉及用户界面甚至编程的概念像CASE, WHILE,或 IF语句等),那么在实际的数据更新过程中效率就会变得很低。
很明显,这是因为在Visual FoxPro中如果要使用事务处理就要求锁住记录。在事务处理和记录更新的过程中,记录被锁住,一直要等到事务处理被委托或者是反转才能够解开。即使你在UNLOCK之后说明了要RLOCK()或者FLOCK(),记录也一直被锁死着,直到END TRANSACTION或者 ROLLBACK出现才会改变。进一步说,把记录悬挂起来也要求Visual FoxPro要把头文件锁住,直到事务处理完成之后才能够解锁。(被委托或者是反转)。因此,在一个大的,多用户的系统中,减少记录被锁死的持续时间是很关键的。所以在上面这个例子中一个更加适当的应用程序是:
* Save method from the cmdSave command button.
BEGIN TRANSACTION
UPDATE PRODUCTS SET reorder_amt = 0 ;
WHERE discontinued = .T.
END TRANSACTION
使用SYS(3051)
这个SYS函数控制时间的数量,精度达到毫秒级,经过一次不成功的锁定尝试之后,Visual FoxPro在再次试图锁定一个记录,表格,索引,或备忘录之前会一直等待。缺省值是333毫秒。
如果在你的数据库文件中有许多锁定竞争,你只要把这个值调大(最大是1000),就能够改善你的应用程序的性能。这样你的应用程序就不会把时间浪费在快速通过网络进行锁定上了。
不过,如果不希望锁定竞争太高,你就要把这个值调低(最小值是100),这样锁定操作就会更快一些。
远程数据性能
从任何后端数据库中检索获得数据都是很耗费时间的。为了从一个服务器数据库中检索数据,以下几个步骤是必须的:
客户端向后端服务器数据库提出查询。
服务器分析并且编辑查询条件。
生成结果集。
服务器通报客户端结果已经完成。
客户端通过网络从服务器上获得数据。
为了加快数据的检索(或更新)过程要用到许多技术。
只检索你需要的数据
一般来说,应用程序中的一个函数单元(在大部分情况下是一个表单或者报表)要访问表格中所有的数据只是特殊情况。建立一个远程视图,仅仅获取(或者更新)你所需要的字段和行,这样通过线路所传送大量数据的情况就会大大改善。例如,如果你已经建立了一个远程视图,它与一个表单的四个控件绑定在一起(如客户表格中的客户标识号,公司名,联系方式,地址等),用这样一个SELECT语句来执行视图,如:
SELECT * FROM customers
效率会很低,因为你检索了大量不做要求的字段。如果用下面这个SELECT语句来执行视图,效果会好一些。
SELECT customer_id, company, contact, address FROM customers
使用WHERE子句
为了限制检索(或者更新)的数据量,适当地使用WHERE子句是有必要的。我们用同样的例子来进行说明,如果你想知道西北地区的客户情况,使用下面这个SELECT语句:
SELECT customer_id, company, contact, address FROM customers
WHERE region = 'NORTHWEST'
WHERE子句中的参数
Visual FoxPro中灵活的视图和SQL Pass Through技术能够让你在SQL SELECT, SQL UPDATE,以及 SQL DELETE语句的WHERE子句中使用运行时参数。例如,你能够从任何区中检索信息。
SELECT customer_id, company, contact, address FROM customers
WHERE region = ?pcRegion
这里pcRegion是参数的名字。如果视图只是用于检索或者再查询必需的信息,这个参数应该有(但不是必须有)。
使用正确的更新准则
View Designer中的Update Criteria标签使你能够明确你想要如何把视图中的数据进行更新,插入和删除。标签中标有“SQL WHERE clause includes”的部分能够让你控制UPDATE 和DELETE操作中WHERE子句的内容。这对于控制后端的数据冲突以及性能都十分重要。考虑到上面所提到的视图并且假设关键字段是customer_id。假设你想要更新除了关键字段之外的所有字段(这种情况不会经常出现,因为改变关键字段就意味着做一次删除再加上一次插入)—也就是“公司名”,“联系方式”,以及“地址”。基于你在"SQL WHERE clause includes"选项组中的选择,你的WHERE子句可以是表1中的任何形式。
Table 1. Possible WHERE Clauses for Updates and Deletions
表1。更新和删除的WHERE子句的可能情况
设置
WHERE 子句
仅仅是关键字段
WHERE OLDVAL (customer_id) = CURVAL (customer_id)
关键字段和经过修改的字段(缺省设置)
WHERE OLDVAL (customer_id) = CURVAL (customer_id) AND
OLDVAL (<first_modified_field>) = CURVAL (<first_modified_field>) AND
OLDVAL (<next_modified_field>) = CURVAL (<next_modified_field>) AND
[and so on.]
关键和可更新的字段
WHERE OLDVAL (customer_id) = CURVAL (customer_id) AND
OLDVAL (company) = CURVAL (company) AND
OLDVAL (contact) = CURVAL (contact) AND
OLDVAL (address) = CURVAL (address)
关键字和时间标记
WHERE OLDVAL (customer_id) = CURVAL (customer_id) AND
OLDVAL (timestamp) = CURVAL (timestamp)
从上表中我们能够很清楚地看出,WHERE子句在很大程度上会影响性能,尤其是有许多字段要更新时(关键字段和经过修改的字段),或者是有许多字段能够被更新时(关键字段和可更新字段)。这是因为Visual FoxPro要把它的"oldval"数据缓冲区中的值(这只是一个系统指针)与硬盘中的值(服务器数据库)相比较,然后及时给出充分的报告说明何时会发生更新冲突(如当你首先获得某些数据时,其他的用户或者程序却改变了这些数据)。如果有很多更新操作要进行,上述比较过程会耗费很多时间。
因此,我们推荐你在大多数情况下使用Key and Modified字段。一般来说,你要更新的后端字段总是你要更新的所有字段的一个子集(同时也是视图中所有字段的一个子集)。
对于支持时间标记的服务器数据库而言,我们推荐你使用Key and Timestamp设置,而不是上面提到的Key and Modified Fields设置。Timestamp是一个行版本,每次行有所改变时,它就要更新一次(顺便提一句,timestamp数据类型并不是指数据和时间,而是指一个数值。你用不着担心不同机器上的系统时钟会导致更新问题。)使用这个设置,在WHERE子句中只比较了其中一列,因此处理速度就快了很多。
注意:这些设置也可以在视图的WhereType属性中通过DBSETPROP()或者CURSORSETPROP()函数进行。
使用BatchUpdateCount 属性
一些服务器数据库(如Microsoft sql server(WINDOWS平台上强大的数据库平台))允许一批批的语句作为一个单独的数据包送往服务器。例如,如果你把BatchUpdateCount属性设置为4,然后更新前10个记录,Visual FoxPro送往服务器的SQL语句就是这样的:
UPDATE customer SET contact = 'John Jones' WHERE customer_id = 1;
UPDATE customer SET contact = 'Sally Park' WHERE customer_id = 2;
UPDATE customer SET company = 'John Jones' WHERE customer_id = 3;
UPDATE customer SET contact = 'John Jones' WHERE customer_id = 4;
这一技术加快了更新,删除,和插入的速度,因为通过线路传送的网络数据包的绝对数量减少了,并且语句被服务器数据库压缩为一批而不是零散的。
你应该试一试用这一属性的不同的值和PacketSize属性来优化你的更新过程。
这个属性也能够在Query菜单的Advanced Options对话框中进行设置,或者是通过编码用DBSETPROP()或CURSORSETPROP()来设置。要注意的是,要利用这种方法的优点则需要用DBSETPROP()或者SQLSETPROP()把Transactions属性中的手动事务处理设为允许。
使用PacketSize 属性
PacketSize属性控制送往数据库服务器的和从数据库服务器中检索获得的网络数据包的大小(以字节计算)。它实际上是由开放式数据库互接(ODBC)来设置的,并且是一个非负值。不同的网络供应商对于这个属性的处理各不相同,所以你需要查看你的网络服务文档。例如,Novell NetWare把数据包大小的最大值设置为512字节,因此在PacketSize属性中,即使把它的值设置得大于512也没有任何其他作用。
PacketSize属性的缺省设置是4096字节。如果你的网络支持更大的数据包大小,你可以把这个属性的值设置为最大数据吞吐量来满足SELECT, INSERT, UPDATE, 和DELETE的要求。
使用FetchMemo 属性
当从后端获取行后,FetchMemo属性能够控制是否要获取备忘录和二进制(普通字段)数据。如果把这个字段设置为.F.,一直到该字段被访问后二进制数据才会被传送到你的机器中。因为获取被延迟到了需要数据的时候,所以查询的获取速度会得到提高。
把查找表格本地化
在许多例子中,只读数据常常被你的应用程序访问。比如说,一个状态表或者一个雇员名称表就可能在你的应用程序中被广泛使用。如果把这些数据本地化(也就是说,不要把每一个查询都上载到服务器中),查找就会变得非常快。对那些从不变化或者很少变化的数据使用这一技术用处最大。
使用本地规则
很少有人知道,Visual FoxPro支持本地字段和记录级别的规则还有远程视图。这些规则能够防止那些与其他数据不同的数据或者不符合企业规则的数据进入数据库中。把这个规则放到视图中而不是后端表格中的好处是,你可以在无效的数据进入线路之前就把它剔除出去。而不利之处就是这个规则不会自动地与后端服务器表格中的规则相匹配。因此,如果你的后端表格规则的定义有所改变,在多数情况下,你需要在本地把视图规则的定义做相应地改变。当然,如果规则很简单,这就不是一个大的负担。还有,规则的定义通常改变得不是很频繁,所以你不要希望能够经常地更新本地规则。
为了使本地规则能够使用,你要用到这个函数DBSETPROP()。下面是一个例子:
* Make sure the order number field is > 0
=DBSETPROP("orders.ordnum")
表单/对象性能
这一部分将介绍在你的应用程序中提高对象性能的技巧,特别是有关表单的性能。
使用数据环境
使用Form Designer 或者Report Designer中的数据环境,表格打开运行速度要比在表单Load事件中执行USE, SET ORDER, 和命令SET RELATION快得多。因为Visual FoxPro使用的是低等级的引擎调用来打开表格,设置索引和关系。
限制表单集中的表单数
表单集仅仅在有许多个表单要共享一个私有的数据会话时才需要用到。当你运行一个Formset时,实际上你就是告诉Visual FoxPro 要在Formset 中建立所有的表单实例以及建立所有这些表单的控件,即使在Formset中只显示了第一个表单。如果这些表单用不着共享私有数据,那么这么做将是非常耗时间的,也完全没有必要。相反地,你应该为其他表单在需要的时候执行DO FORM。
从另外一个方面来说,如果你真的用了Formsets ,在访问Formsets中的表格时,你会发现性能有所提高,因为它们已经加载了,只不过看不见。
在Pageframe中动态加载Page Controls
Pageframes,像Formsets一样,在加载Pageframes时就把每一页的所有控件都加载了。你可以用这个技术在Pageframes的每一页中建立一个超出控件之外的类别。
你的目标是延迟看不见的页面上的控件的实例化,直到用户访问这些页面为止。以下是步骤:
如以往一样设计你的表单,其中包括所有页面中的控件。
设计完成之后翻到第二页,把你觉得要合并为一类的控件省下来。
打开你建立的类,确保这些控件能够完全打开。
在以下的页中重复第二步和第三步。
在第二页及以下页的激活方法中,加入下列代码:
IF This.ControlCount=0
This.Addobject("cnrpage1","cnrpage1")
This.cnrpage1.visible=.T.
ENDIF
用这种技术你能够加快表单的加载速度,因为 Pageframe第二页之后的页面中的控件如果不需要就不会被加载了。
把控件和数据进行动态绑定
对于那些有许多要绑定数据的控件的表单,如果你能够把这些绑定推迟到需要的时候再进行,你就会发现它的性能有了很大的改善。
你能够把表单的表格和视图放到Data Environmen中,这样一来,当表单加载时,它们也就被打开了。然后,如果选中一个控件—例如一个组合框—,你就可以把控件与数据值绑定在一起。在下面这个例子中,联合方框已经与GotFocus事件中的"customer.company"字段绑定在一起。
*检查一下是否控件已经被赋值。
IF this.RecordSource = ""
*把记录资源设置为正确的值
*把记录资源类型设置为“字段”
this.RecordSource = "customer.company"
this.RecordSourceType = 6
* Refresh the control.
this.Refresh
ENDIF
对要绑定数据的控件使用这个技术,可以大大改进表单的加载时间。
使用LockScreen
这一特性让你能够延迟表单中控件的任何变化所引起的屏幕刷新的速度。例如,如果你要让控件看得见或者看不见,要改变控件的颜色,或者是要移走绑定控件中的记录,等到这些全部完成之后再显示这些控件,效率会比较高。
thisform.LockScreen = .T.
thisform.MyButton.Caption = "Save"
thisform.MyGrid.BackColor = RGB (255, 0, 0) && Red
SKIP IN customers
SKIP IN orders
thisform.Refresh
thisform.LockScreen = .F.
在这个例子中,我们设置了一个标题,改变了背景颜色,并且把所有与客户和顺序绑定的控件中的记录都移走了。如果没有LockScreen特性,你将会看到以上的每一个操作都会引起相应控件的外观变化,所有的更新过程都会变得缓慢不已而不是利索爽洁。
如果需要对一个表单的显示多次进行改变时,通常你会用到这一技术。我们不是让你在每一次显示改变时都使用LockScreen,而只是像上面这个例子中所描述的一样,在有一组改变时使用它。
利用WITH … ENDWITH 或者使用Object References
当你要用“对象特性”语法说明了一个对象的特性时,Visual FoxPro必须首先在能够访问该特性之前首先找到这个对象。例如,下列编码是要Visual FoxPro通过查找四个对象(thisform, pgfCustInfo, pagCustName, 和cboName),找出三个特性中要设置哪个特性:
thisform.pgfCustInfo.pagCustName.txtName.Value = "Fred Smith"
thisform.pgfCustInfo.pagCustName.lblName.Caption = "Name"
thisform.pgfCustInfo.pagCustName.grdOrders.BackColor = RGB (0,0,0)
lcSeek = ALLTRIM(thisform.pgfCustInfo.pagCustName.txtName.Value)
如果你接下来要设置一个对象的两个或者更多个特性,则使用WITH…ENDWITH结构。这么做,Visual FoxPro就只需确定其范围并且找到该对象一次。在上面这个特性设置的例子中,用到WITH…ENDWITH就会快得多:
WITH thisform.pgfCustInfo.pagCustName
.txtName.Value = "Fred Smith"
.lblName.Caption = "Name"
.grdOrders.BackColor = RGB (0,0,0)
lcSeek = ALLTRIM(.txtName.Value)
ENDWITH
注意:就像在ALLTRIM函数中所说明的一样,你可以在WITH … ENDWITH结构的任何地方使用<.objectname>语法。
能够做到这一点的另外一个方法就是利用对象引用。对象引用不过是一个控制对象引用的变量。还是以上面的例子为例说明,你也可以这么做:
oPageFrame = thisform.pgfCustInfo.pagCustName
oPageFrame.txtName.Value = "Fred Smith"
oPageFrame.lblName.Caption = "Name"
oPageFrame.grdOrders.BackColor = RGB(0,0,0)
在上面这个例子你不一定会见到有很明显的性能改善,但是如果一个对象(在这个例子中是pagCustName PageFrame对象)在你的应用程序中或者在一个循环中被多次引用,性能一定会有很大地提高。
使用多分配的变量
访问全部的<container.object.property>要比访问一个变量慢。这一点在一个程序的循环中尤其明显。典型的面向对象的程序的做法是如果一个对象的特性被反复用到,就把它的内容复制到一个变量中。例如,下面这些代码就填充了一个特性数组:
FOR x = 1 to 256
thisform.aCharArray[x] = SUBSTR(thisform.cCharString, x, 1)
ENDFOR
而在下面这些代码中,尽管要执行的代码显得比较多,但是它们的确要快一些,因为<object.property>这个代码在循环外就已经被赋值了:
*把字符串复制给一个本地变量。
lcChar = thisform.cCharString
*建立一个本地数组。
LOCAL laCharArray[256]
FOR nCounter = 1 to 256
laCharArray[x] = SUBSTR(laChar, x, 1)
ENDFOR
*把本地数组复制到特性数组中。
=ACOPY(laCharArray, thisform.aCharArray)
在Init, Refresh,和 Paint Methods中尽量避免大量的Xbase代码
这些事件经常出现,你一定要消除(或减少)在这些方法中用到代码。尤其是对于Refresh和 Paint方法而言,它们使用得最频繁。
把Init代码转移到用得不那么频繁的方法中,如Activate, Click,和 GotFocus等。然后你就可以在一个控件中使用一个特性,而且只需要运行一次来跟踪是否该控件已经运行了代码。
在视图中使用NoDataOnLoad特性
在一个视图的Data Environment Cursor 对象中的NoDataOnLoad特性与视图的USE命令中的NODATA子句作用是一样的。它使得视图被打开,但是视图并没有真正获得任何数据。无论是本地视图还是远程视图都是这样的。
一般来说,你在Data Environment中已经设置了参数的视图上可以使用这一技术(详细情况请见“为你的WHERE子句设置参数”)。例如,你有一个客户信息表单,它使用了一个设置了参数customer_id的视图。你可以键入一个无效的customer_id,然后按下查找键。查找按钮的代码与下面的这些代码很相似(假设该视图的参数叫做vpCustID,这里vp是用于表示一个作为视图参数的变量的匈牙利语符号):
*把视图参数设置为客户标识符文本框中的值。
vpCustID = thisform.txtCustomerID
*锁住屏幕延迟画面改变。
thisform.LockScreen = .T.
*发出视图中的再查询。
=REQUERY('customerview')
*刷新数据绑定控件
thisform.Refresh
*为屏幕开锁。
thisform.LockScreen = .F.
这些代码是一个简单的例子,但是它是处理本地的和远程的已经设置了参数的视图的典型方法。
这么做的好处是表单载入时间大大减少,因为视图不会使任何数据回送给你,给客户。那些与视图的字段绑定了的控件仍然绑定着,因为这里是一个公开工作区(没有数据在里面)。
OLE 性能
在你访问OLE数据之前你要打开OLE服务器。与普通字段绑定的控件在这一类数据(如Microsoft Word 或者Microsoft Excel)的服务器已经在客户机上运行时要表现得比较好。
Automation性能
在某些例子中,Automation服务器(如Microsoft Excel)总是开始一个自己的新实例,即使当前已经有一个实例在运行了也是如此。为了改变这种情况(同时提高性能),要使用GetObject函数而不是CreateObject函数。例如下面这个调用:
x = GetObject(, "excel.Application")
就会使用现有的实例,而:
x = CreateObject("excel.Application")
就会建立一个新的实例。
当你使用GetObject时,如果服务器没有运行,你就会收到Visual FoxPro发出的一个错误信息,此时你要捕获这个错误并且调用CreateObject()函数。
不要反复用子对象来评价长表达式。执行使用OLE服务器中对象的表达式会花费很多时间,特别在是要进行多次评价时。如果把子对象缓存到变量中用于引用就会快很多(详细情况请见为多次赋值使用变量)。
把对象作为图标插入
当你要把一个OLE对象插入到一个字段中时,你可以把它作为一个图标或者是一个占位符而不是作为一个整的对象来插入字段中。这么做能够减少需要的存储空间,因为Visual FoxPro存储的是对象的简报图象。同时在拖拽对象时性能也会有所提高,因为此时只有图标需要变换。
使用图象控件
如果在一个应用程序中需要用到一个位图,如一个公司的徽标,Image Controls比 OLEBoundControls.要快得多。
可能时使用手工链接
手工与对象进行链接比较地快,因为在自动链接时需要的通告时间在这里可以省略掉,同时也因为在拖拽对象时不需要开始OLE服务器。如果你不需要经常更新对象,那么最好用手工链接。
内存管理
使用SYS(3050)
这个SYS函数能够让你优化用于数据缓存的前台和后台的内存。前台内存是指当Visual FoxPro是前台应用程序时所用的内存。而后台内存是指当Visual FoxPro是一个后台应用程序时所用的内存。
为了优化你的应用程序,你可以尝试不同的值,让Visual FoxPro有不同的内存来用于数据缓存。
不要使用MEMLIMIT
Visual FoxPro不认识MEMLIMIT,在FoxPro 2.6中, MEMLIMIT是指用于说明FoxPro能够分配使用的最大内存的配置设置。不要用这个配置来限制Visual FoxPro能够使用的最大内存。如果需要的话就用SYS(3050)。
谨致谢意
尽管这篇文章是由我来执笔写成的,但我还是要感谢Visual FoxPro组的成员们,他们是Geoff Kizer, Tom Cooper, Lori Sargent, Rodney Hill, Dave Berliner, Matt Pohle以及其他Visual FoxPro性能组的成员。如果没有他们的帮助我将很难完成这篇文章。
我还要感谢George Goley of MicroEndeavors, Inc.,和 David T. Anderson of Alden Anderson Consulting, Inc,他们提供了许多技巧并且还为我审查了这篇文章。再次表示感谢!
- ››Visual Basic 2008 数学函数
- ››Visual Studio2005中Smart Device的问题
- ››Visual Studio 中根据数据库字段动态生成控件
- ››Visual Studio 11全新黑色主题
- ››Visual Studio 2011 Beta新特性(一):安装VS201...
- ››Visual Studio自定义调试窗体两个小技巧
- ››Visual Studio 2005 Team Edition for Database P...
- ››Visual C#两分钟搭建BHO IE钩子
- ››Visual C++优化对大型数据集合的并发访问
- ››VISUAL C++中的OCX控件的使用方法
- ››Visual C++实现视频图像处理技术
- ››Visual C++制作一个Sniffer实例
更多精彩
赞助商链接