设为首页   |  加入收藏夹 快速导航:  热门文章  |  最新文章  |  梦想博客  
当前位置:编程之家 -> 文章频道 ->vf 
站内搜索:  

Microsoft Visual FoxPro的性能调整技巧(2)

作者:佚名 来源:不详 整理日期:2007-04-15

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,他们提供了许多技巧并且还为我审查了这篇文章。再次表示感谢!
[1]  [2]