发信人: garfieldmao()
整理人: winsy(2003-03-06 12:51:16), 站内信件
|
优化Visual Basic应用程序
目前的硬件条件比起前些年虽然已有了很大的改善,但应用程序的性能仍然受到 处理器
速度、内外存空间及网络连接等诸多因素的制约,为了在有限的硬件资源的前提 下,尽
可能地提高应用程序的效率和性能,必须在设计和编写应用程序时缩小应用程序 的大小
、提高计算和显示的速度,进而优化所创建的应用程序。
程序的优化大体上可以分为两种:时间上的优化和空间上的优化(本文把这两种 优化分
别称为“速度优化”和“大小优化”)。下面,笔者从这两个方面谈谈对Visual Basic
应用程序的优化方法。
一、速度的优化
在用户评测应用程序是否满意的诸多因素中,速度是决定性的因素。所以,有必 要优化
创建的应用程序,加快其速度。
程序的速度可以分为三种:真实速度(执行代码的实际时间)、显示速度(屏幕 显示的
时间)和感觉速度(应用程序运行时的感觉速度)。
1、真实速度的优化
为了加快Visual Basic程序的真实速度,使代码计算或运行的更快,可采用以下 的几种
技术
(1).避免使用 Variant 变量
Variant(变体型)变量是Visual Basic的缺省变量类型,程序中凡是未加类型说 明的变
量均认为是变体型变量,使用这种变量对于初学者以及处理速度不成问题的应用 程序来
说,是非常方便的。然而,如果想提高应用程序的实际速度,就要避免使用变体 型变量
。因为,在运行时Variant将转化为其它适当的数据类型,而转化的过程是需要时 间的。
如果直接采用其它简单的数据类型,就可以避免不必要的类型转换操作而加快应 用程序
的速度。
避免使用Variant变量的好办法是让Visual Basic自动地在每个模块前加上Optio n Expl
icit 语句,这样所有的变量在使用前都必须进行声明。方法是:在“工具”菜单 中启动
“选项”对话框,选择“编辑器”选项卡,选定“要求变量声明”复选框,该设 置对之
后所有新建的模块起作用。
有一点需要注意,由于Visual Basic的变量声明可以不定义变量类型,所以即使 经过了
声明,如果未加类型限制,也会产生Variant变量。
特别是在声明多个变量时要小心,Visual Basic有一个“怪癖”,它无法在一条 声明语
句中仅使用一个As type来同时说明多个该类型的变量(这一点不知在Visual Ba sic 6.
0中是否会有所改变),在下面的例子中,Z被声明成Long型,而X和Y是仍是Vari ant变量
:
Dim X, Y, Z As Long
为了将X和Y也声明成Long型变量,需重写语句如下:
Dim X As Long, Y As Long, Z As Long
(2).选用最佳的数据类型
程序中要尽量避免使用Currency、Single和Double变量,并尽量使用Long整型变 量,尤
其在循环体中。因为Long整数是32位CPU的本机数据类型,所以其操作非常快。如 果无法
使用 Long 变量,就要尽量使用Integer或Byte数据类型。很多时候,即使在要求 使用浮
点数的情况下,也可以使用 Long 整数。例如,在窗体和图形控件的 ScaleMode 属性设
置为缇或象素时,就可以在控件和图形方法中使用Long整型变量表示大小和位置 。
进行除法运算时,结果如果不需要小数部分,就可以使用整数除法运算符 (/)。 由于浮
点运算需要转移到协处理器上进行,而整数运算并不需要,所以整数运算总是比 浮点运
算快。如果确实需要做小数运算,则应选取相对较快的数据类型。在Visual Bas ic中各
种数值数据类型的运算速度顺序如下(由快到慢):
Long->Integer->Byte->Single->Double->Currency
(3).将常用的属性值、函数返回值缓存在变量中
一般来说,变量的处理速度比同类型的属性处理速度快许多,因此如果经常用到 某一属
性的值(如在循环体中),应该先将该属性值赋给某一变量,以后用该变量替代 该属性
,这样就能够提高代码的速度。例如,象这样的代码就比较慢:
For i = 0 To 10
label(i).Left = text1.left
Next i
下面改写的代码就要快得多:
LabelLeft = text1.left
For i = 0 To 10
label(i).Left = LabelLeft
Next i
同样的技术可用于处理函数的返回值,用变量缓存函数的返回值,避免经常调用 运行时
的动态链接库,也会大幅度地提高速度,如:某程序中多次用到Mid(Text1.text) ,则可
先用一变量TempString保存Mid(Text1.text)的值,之后凡是用到该函数的地方一 律用T
empString代替。
(4).使用内嵌过程替代过程调用
采用过程调用使代码更具有模块化的风格,但过程调用总是增加额外的操作和处 理时间
。如果循环体中多次调用某一过程,就可以直接把该过程写到循环体中去,以消 除过程
调用时的额外负担。
但另一方面,直接把某一过程写到好几个循环体中时,重复的代码无疑要增加应 用程序
的大小;同时,在更改程序时,有可能忘记更改这些重复的代码,这就增加了出 错的机
会。因此,在使用内嵌过程时要仔细权衡利弊。
(5).尽可能使用常数
使用常数是一项非常好的编程习惯,常数不仅可以加快应用程序的运行,而且还 可增强
代码的可读性,使之易于维护。如果代码中的字符串或数字是不变的,则可把它 们声明
为常数。常数是在编译时进行处理的,编译程序用适当的值替换代码中常量,而 变量在
每次运行时都要读取当前值。
(6).尽量用ByVal传递参数,而不用ByRef
编写含参数的Sub或Function时,按值(ByVal)传递参数比按地址(ByRef)快。尽管 Visu
al Basic中参数传递的缺省方式是ByRef,但实际上需要改变参数值的过程极少( ByRef
的目的就是为了允许在过程中改变参数的值)。如果过程中不需改变参数的值, 就可以
按值(ByVal)来传递,ByVal的用法如下:
Private Sub DoSomething(ByVal AuthorName As String)
(7).正确地选择集合和数组
如果多个对象的类型一样,集合或数组都可以用来管理这些对象(如果对象的类 型不一
样,则只能用集合)。从速度的观点看,选择何种方式取决于对象的访问方式。 如果能
够为每一对象分配唯一的关键字(如Name属性),则集合是访问对象的最快方式 。。而
对顺序遍历方式而言,数组比集合快,所以当没有关键字而要遍历对象时,则选 择数组
比较好。
(8).尽量少用点操作
当从Visual Basic中引用其它应用程序的对象时,可使用点语法“.”对对象的集 合、属
性和方法等进行应用。然而每一个“点”都需要Visual Basic产生多次调用,因 此为了
写出最有效的应用程序,引用对象时应尽量少使用多余的点操作。以下的方法可 减少“
点”的使用。
a.使用缺省的方法和属性
当对象使用缺省的方法或属性时,可以省略该方法或属性,也就减少了一次“点 ”的使
用,如:
Label1 = Text1
在功能上相当于:
Label1.Caption = Text1.Text
但确减少了“点”的使用次数。
b.使用Set语句
Set语句可缩短定位字符串,并提供对代码更灵活的控制。下例使用Dim和Set语句 创建变
量,使其引用经常使用的对象:
Dim xlRange As Object
Set xlRange = Application.ActiveSheet.Cells(1,1)
xlRange.Font.Bold = True
xlRange.Width = 40
c.使用With...End With
利用Visual Basic提供的With...End With语句,不仅可以大大地减少“点”的使 用,同
时还使代码简洁易读。如上例可改写为:
With Application.ActiveSheet.Cells(1,1)
.Font.Bold = True
.Width = 40
End With
2、显示速度的优化
在Windows的图形环境下,加快图形和其它操作的显示速度对整个程序的速度的提 高起非
常重要的作用。以下的几种技术可用来提高应用程序的显示速度:
(1).将容器的ClipControls属性设置为False
如果不使用图形方法(Line,Pset,Circle 和 Print等),就可以将窗体、框架 及Pic
tureBox控件的ClipControls属性设置为 False。这样在重画控件本身之前,Vis ual Ba
sic不会用背景覆盖控件,这在窗体包含大量控件时,会大大提高显示速度。
(2).恰当地使用AutoRedraw
当窗体或控件的 AutoRedraw属性设置为True时,Visual Basic会利用位图重画该 窗体或
控件。这种方法虽然提高了简单情况的重画速度,但会降低图形方法的速度。
如果应用程序产生的图形复杂但是不常改变,AutoRedraw设置为True 较为合适。 如果图
形需要经常改变,则AutoRedraw设置为False的效果更好。
(3).用Image控件替代PictureBox控件
PictureBox控件比Image控件的功能要强,如提供了图形方法、包含其它控件的能 力或动
态数据交换 (DDE)能力,因此它的处理时间也相对Image控件较长。如果仅简单显 示图片
,或只对简单的鼠标操作作出响应,则应使用Image控件替代 PictureBox。
(4).设置属性时隐藏控件以避免多次重画
重画的代价是昂贵的,重画操作越少,应用程序就越快。减少重画次数的一种方 法,就
是在改变控件属性时使其不可见。例如,假设在窗体的Resize事件中调整数个列 表框的
大小:
Sub Form_Resize ()
Dim i As Integer, sHeight As Integer
sHeight = ScaleHeight / 4
For i = 0 To 3
lstDisplay(i).Move 0, i * sHeight, ScaleWidth, sHeight
Next
End Sub
上面的代码产生四次独立的重画,每个列表框一次。可以把所有的列表框放在一 个图片
框中,并在移动或调整列表框大小之前隐藏图片框,就会减少重画的次数。当再 次使图
片框可见时,所有的列表框一次画出,修改后的代码如下:
Sub Form_Resize ()
Dim i As Integer, sHeight As Integer
picContainer.Visible = False
picContainer.Move 0, 0, ScaleWidth, ScaleHeight
sHeight = ScaleHeight / 4
For i = 0 To 3
lstDisplay(i).Move 0, i * sHeight, ScaleWidth, sHeight
Next
picContainer.Visible = True
End Sub
在上面的两段代码中还显示了另外一种减少重画次数的技巧,即使用Move方法替 代设置
Top和Left属性。Move方法只需一次操作就设置了这两个属性,所以节省了多余的 重画。
3、感觉速度的优化
通常,应用程序的感觉速度和代码的实际执行速度并无多大关系。对用户来说, 启动快
、绘画快并提供不间断的反馈信息的应用程序显得速度快;而在完成任务时似乎 “悬挂
”起来的应用程序则显得速度慢。许多技术都可以使应用程序显得速度快:
(1).隐藏窗体而不加载
在暂时不需要某个窗体时,把它隐藏起来而不是把它们卸载,是一项提高显示速 度和感
觉速度的非常有效的技巧,这样当再次需要该窗体时,不需要额外的时间去加载 窗体,
只需简单地使用Show方法即可。这项技术的负效应是要占用一定的内存。但如果 能够提
供足够的内存,而且窗体能够快速出现被认为是最重要的,则可以采用这项技术 。
(2).预加载数据
预先读取数据也可以改善应用程序的感觉速度。例如,需要从磁盘上加载某个文 件时,
可以顺便加载其它后面会用到的文件,加载额外的文件增加的时间也许并不会被 觉察到
,而且以后不会再次出现延迟。
(3).使用进度指示器和等待光标
如果程序中存在不可避免的长时间延迟,则必须给用户以提示,说明应用程序并 没有悬
挂起来。可以使用标准的进程指示控件ProgressBar来提示用户,至少也应设置窗 体的M
ousePointer属性为vbHourglass(11),这样就会显示等待光标来表明程序正在运 行。
(4).加快应用程序的启动速度
用户对应用程序的印象好坏往往取决于程序的启动速度,因此应尽可能地加快程 序的启
动速度。可以使用以下两种方法提高启动速度:
a.简化启动窗体
窗体越复杂,其加载的时间就越长,所以要使启动窗体尽量简单。启动窗体上的 控件越
少,包含的代码越少,则其加载和出现的速度就越快。可以在应用程序启动时先 显示一
份简洁的版权屏幕,然后再加载其它更复杂的窗体(这时,可利用进度条),这 样当启
动版权屏幕时,用户已知道应用程序已经启动。
b.不要加载不需要的模块
Visual Basic根据要求加载代码模块,只有调用了某模块中的过程时,才会加载 该模块
,未被调用的模块不会被加载。如果启动窗体调用了数个模块中的过程,则应用 程序启
动时将加载所有这些模块,这就会降低速度。所以应避免从启动窗体中调用多个 模块的
过程,换句话说,就是应该将启动窗体所有调用的过程放在一个模块中,这样启 动时只
需加载一个模块。
二、大小优化
缩小应用程序的大小不仅可以节约系统资源(减少内外存的占用),同时由于较 小的应
用程序加载的速度较快也可能带来速度的提升,因此,也应对程序的大小进行优 化。
1、减少加载窗体的数目
每一个加载的窗体,无论可视与否,都要占据一定数量的内存(其数量随窗体上 控件的
类型和数量,以及窗体上位图的大小等的不同而变化)。只在需要显示时才加载 窗体,
不再需要时,卸载窗体(而不是隐藏窗体)。卸载窗体最好的办法不是Unload, 因为Un
load只能释放部分窗体所占空间,要释放所有空间,可用关键字Nothing使窗体的 引用无
效:
Set Form = Nothing
非常遗憾的是,这一条减少内存占用的原则与上述加快速度的原则相抵触,具体 采用哪
一种优化,需根据具体情况而定。
2、减少控件数目
当设计应用程序时,窗体应尽量少用控件,含有大量控件的窗体将运行缓慢。必 须使用
许多控件时,也应尽可能地使用控件数组,而不是在窗体上放置大量同类型的控 件。
3、用标签代替文本框
标签控件占用的 Windows 资源比文本框少,因此,在可能的情况下,应使用标签 代替文
本框。例如,当窗体上需要一个隐藏的控件保存文本时,使用标签更有效。
4、保持数据在磁盘文件或资源中,并且只在需要时才加载
在设计时,直接放入应用程序的数据(象属性或代码中的文字字符串和数值)将 增加运
行时应用程序占用的内存。运行时从磁盘文件或资源中加载数据可减少占用内存 。特别
是对图形、图象和大的字符串更是如此。
5、组织模块
前面已经提到,将相关的过程放在同一模块中可加快程序的启动,这条原则也同 样用于
减少内存的占用。尽量把相关的过程放在同一模块,让Visual Basic只在需要时 才加载
其它模块,这样可避免加载无用(至少是暂时无用)的模块,以达到减少内存占 用的目
的。
6、使用简单的数据类型
简单数据类型,不仅运行速度较快,其占用的内存也少,因此,应尽量使用简单 的数据
类型,特别要少使用Variant的变量数组,因为变体型数据占用的内存远大于其它 类型数
据。
但要注意,在有些情况下,使用其它数据类型替代Variant,灵活性降低了,为弥 补损失
的灵活性,不得不增加更多的代码。结果是程序的大小不仅没有减少反倒是增加 了,要
避免这种得不偿失的做法。
7、使用动态数组
使用动态数组代替固定数组可以节省内存占用,需要时,还可用Erase删除动态数 组或R
eDim Preserve减少数组大小。而对于固定大小的数组,是无法将其所占的内存收 回的(
除非数组的生命周期结束)
8、消除死代码和无用的变量
在开发和调试应用程序时,可能遗留了死代码(绝对不可能执行到的代码),也 可能声
明了一些无用的变量。注意要复查代码,查找并删除无用的变量和死代码。
当然,就像绝大多数语言一样,Visual Basic在编译时忽略注释语句,所以没有 必要删
除注释语句。
9、用Image控件代替PictureBox控件
这是另一项既优化速度,又优化大小的技术。正如前文所述,当不需要使用Pict ure 控
件的特殊功能时,可用Image控件代替PictureBox控件,这样可以节省大量的系统 资源。
10、共享图片
如果在设计时将相同的图片加载到几个窗体或控件中,每一个窗体或控件都存储 了该图
片的一个副本。然而如果将图片存于一个窗体中,而让其它窗体或控件共享该图 片,这
样既可减少程序的大小(因为不包含冗余的图片拷贝)又可加快速度(因为不必 从磁盘
中多次加载)。如下面的代码:
Picture = LoadPicture("C:\Windows\Chess.bmp")
Image1.Picture = Picture '使用相同的图片。
Picture1.Picture = Picture '使用相同的图片。
比下列加载了同一位图的三个副本的代码要好得多。
Picture = LoadPicture("C:\Windows\Chess.bmp")
Image1.Picture = LoadPicture("C:\Windows\Chess.bmp")
Picture1.Picture = LoadPicture("C:\Windows\Chess.bmp")
以上,笔者就Visual Basic程序的优化介绍了一些常用的技巧,由于影响应用程 序性能
的因素非常多,所以对程序的优化要远比上述情况要复杂得多,欢迎广大读者就 程序的
优化提出自己独特的见解。
作者:王卫
联系地址:新疆钢铁集团公司自动化技术有限公司
邮政编码:830022
电话:0991-3891603
E-mail:[email protected]
-- ┏━━━━━━━━━━━━━━━━━━━━━┓
┃请在[将本文章寄一份给原作者]之后打“√”。┃
┃ 猫仔 OICQ:1251089 ┃
┃ Email:[email protected] ┃
┃ VB编程园 Http://maozai.home.china.com ┃
┗━━━━━━━━━━━━━━━━━━━━━┛
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.105.152.16]
|
|