使用 Windows 窗体和图形节省内存
-
对提供 BeginUpdate 和 EndUpdate 方法的控件使用这两种方法,提供这两种方法的控件包括 <link tabindex="" keywords="T:System.Windows.Forms.ComboBox">、<link tabindex="" keywords="T:System.Windows.Forms.ListBox">、<link tabindex="" keywords="T:System.Windows.Forms.ListView">、<link tabindex="" keywords="T:System.Windows.Forms.ToolStripComboBox"> 和 <link tabindex="" keywords="T:System.Windows.Forms.TreeView">。
-
重新定位控件时,使用 <link tabindex="" keywords="M:System.Windows.Forms.Control.SuspendLayout"> 和 <link tabindex="" keywords="M:System.Windows.Forms.Control.ResumeLayout"> 方法。
-
在后台加载其他窗体,使用数据来填充控件,然后再使用 <link tabindex="" keywords="M:System.Windows.Forms.Control.Show"> 方法。
-
将事件处理代码限制为仅执行重要任务,以便挂起过程可以继续。
-
使用脱屏位图。有关示例,请参见如何:绘制后台图像。
-
重写控件上的 <link tabindex="" keywords="M:System.Windows.Forms.Control.OnKeyDown(System.Windows.Forms.KeyEventArgs)">、<link tabindex="" keywords="M:System.Windows.Forms.Control.OnKeyPress(System.Windows.Forms.KeyPressEventArgs)"> 和 <link tabindex="" keywords="M:System.Windows.Forms.Control.OnKeyUp(System.Windows.Forms.KeyEventArgs)"> 方法,而不是添加按键事件处理程序。
使用数据和字符串节省内存
-
在 for 循环中使用整数变量(<link tabindex="" keywords="T:System.Int32"> 或 <link tabindex="" keywords="T:System.Int64">),而不使用对象变量。
-
避免使用枚举的 <link tabindex="" keywords="M:System.Enum.ToString"> 方法,因为它会搜索元数据表,从而影响性能。
-
避免 <link tabindex="" keywords="T:System.OutOfMemoryException"> 错误。如果没有足够的内存分配给内部使用或分配给新对象实例,公共语言运行库可能会引发此异常。要避免此异常,应避免编写占用 64K 或更多内存的大方法。
-
移除 System.SR.dll,它包含异常对话框的错误信息字符串。部署应用程序时可以不使用此文件,从而节省内存。如果存在 System.SR.dll,则 .NET Compact Framework 将动态加载 System.SR.dll 中包含的错误字符串。
如果设备中不存在此 .dll 文件,则所有异常都包含消息“无法加载资源程序集”。不过,在开发期间将 System.SR.dll 引用添加到 Microsoft Visual Studio 2005 项目中总是有用的,因为这样您将看到有意义的异常。
-
字符串是不可变的,因此,每次修改该字符串时都会创建新的 <link tabindex="" keywords="T:System.String"> 对象。构造需经常修改的字符串时,请考虑使用 <link tabindex="" keywords="T:System.Text.StringBuilder">。
-
如果您知道用于 <link tabindex="" keywords="T:System.DateTime"> 序列化的确切格式,请为 DateTime 使用 <link tabindex="" keywords="Overload:System.DateTime.ParseExact"> 方法。否则,DateTime 分析器将按顺序尝试应用多个特定于区域性的格式。
-
限制打开 <link tabindex="" keywords="T:System.Data.SqlServerCe.SqlCeCommand"> 对象的数量,并在完成后释放它们。
与本机代码进行交互时节省内存
-
在平台调用操作中,使用可直接复制到本机结构中的类型,这样的类型在托管和非托管内存中有一种通用表示形式,如 Int32 或 <link tabindex="" keywords="T:System.IntPtr">。对于大于 32 位的可直接复制到本机结构中的值类型来说,通过引用传递比通过值传递更快。有关可直接复制到本机结构中的类型的更多信息,请参见 .NET Compact Framework 中可直接复制到本机结构中的类型。
-
为函数签名中的参数使用 <link tabindex="" keywords="T:System.Runtime.InteropServices.InAttribute"> 和 <link tabindex="" keywords="T:System.Runtime.InteropServices.OutAttribute"> 属性可以减少不必要的封送处理。
-
使用 <link tabindex="" keywords="T:System.Runtime.InteropServices.Marshal"> 类中的方法手动在 IntPtr 和托管对象之间转换,如 <link tabindex="" keywords="M:System.Runtime.InteropServices.Marshal.PtrToStructure(System.IntPtr,System.Type)">、<link tabindex="" keywords="M:System.Runtime.InteropServices.Marshal.PtrToStringBSTR(System.IntPtr)">、<link tabindex="" keywords="M:System.Runtime.InteropServices.Marshal.GetObjectForNativeVariant(System.IntPtr)"> 和 <link tabindex="" keywords="M:System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(System.IntPtr)">。
-
使用 <link tabindex="" keywords="M:System.Runtime.InteropServices.Marshal.Prelink(System.Reflection.MethodInfo)"> 和 <link tabindex="" keywords="M:System.Runtime.InteropServices.Marshal.PrelinkAll(System.Type)"> 方法来引发支持本机到托管调用的存根 (stub) 的 JIT 编译。
-
如果期望您的本机 COM 对象通常情况下返回 S_FALSE,或其他非 S_OK HRESULT 值,则应将 <link tabindex="" keywords="F:System.Runtime.InteropServices.DllImportAttribute.PreserveSig"> 字段设置为 true,并使托管签名与本机签名匹配。这就避免了运行库将 HRESULT 值转换为 COM 调用上的异常时必需的 try/catch 块的系统开销
。
-
尽量使用一个平台调用多做工作,尽量少用多个调用。
在集合中节省内存
-
如果集合基于数组,请使用索引器。
-
一旦有机会,就指定集合的大小,因为动态调整大小可以大大增加额外的存储。
-
使用泛型集合以避免值类型的装箱和取消装箱产生的系统开销。定义您自己的优化集合可实现最佳性能。
在 XML 中节省内存
-
使用 <link tabindex="" keywords="T:System.Xml.XmlTextReader"> 和 <link tabindex="" keywords="T:System.Xml.XmlTextWriter"> 代替 <link tabindex="" keywords="T:System.Xml.XmlDocument">(因为它占用的内存较多)。
-
指定 <link tabindex="" keywords="T:System.Xml.XmlReaderSettings"> 和 <link tabindex="" keywords="T:System.Xml.XmlWriterSettings"> 的设置以改善性能。如果 <link tabindex="" keywords="P:System.Xml.XmlReaderSettings.IgnoreWhitespace"> 和 <link tabindex="" keywords="P:System.Xml.XmlReaderSettings.IgnoreComments"> 两个属性值适用,它们可以显著改善性能。
-
使用 UTF-8、ASCII 和 UTF-16 字符编码,它们比 ANSI 和 Windows 代码页编码更快。
-
避免使用用于分析的架构,因为这种架构需要更多的验证工作。
-
当从 XML 源填充 <link tabindex="" keywords="T:System.Data.DataSet"> 窗体时,应将列映射为属性并使用类型化 DataSet。
-
填充 DataSet 时,应避免填充以下各项:
-
架构推理。
-
嵌套表。
-
多个 DateTime 列。为了获得更好的性能,请使用 <link tabindex="" keywords="P:System.DateTime.Ticks"> 属性值。
-
-
使用 XML 反序列化时,遵循以下准则可改善性能:
-
使元素和属性名尽量保持简短,因为每个字符都必须经过验证。
-
基于属性数据的 XML 比基于元素数据的 XML 要快。
-
如果适用,使用 <link tabindex="" keywords="M:System.Xml.XmlNodeReader.Skip"> 方法。
-
如果性能很重要,应考虑二进制序列化。
-
-
为 XML 序列化的每一种类型分别使用一个 <link tabindex="" keywords="T:System.Xml.Serialization.XmlSerializer"> 实例,以减少用于搜索元数据的时间。
-
由于序列化大量 XML 可能会耗尽内存,应考虑通过使用 <link tabindex="" keywords="T:System.IO.BinaryReader"> 和 <link tabindex="" keywords="T:System.IO.BinaryWriter"> 生成自定义二进制序列化机制。
使用 Web 服务时节省内存
-
读取和编写 DataSet 时,应使用 DiffGram。有关更多信息,请参见 <link tabindex="" keywords="037f3991-7bbc-424b-b52e-8b03585d3e34">。
-
以 XML 格式将远程 DataSet 及其架构保存到设备。
-
初始屏幕期间创建一个简单的 Web 服务方法调用,因为第一个调用比后面的调用要慢。
-
小心处理网络和数据错误。
-
某些情况下,可以手动将 DataSet 序列化为 XML 字符串,然后执行一个 Web 服务调用,这样可以提高性能。
在高级编程中节省内存
-
异步处理大操作。
-
避免虚拟调用。.NET Compact Framework 运行库虚拟调用比静态调用或实例调用大约慢 30%。由于资源受约束,.NET Compact Framework 不使用 vtable,因此必须通过转换类和接口层次结构来调用方法,但这是一种代价很高的操作。.NET Compact Framework 维护已解析的虚拟调用的缓存,因此在大多数情况下,无须重新解释调用。
-
尽可能使用字段而不使用属性。
-
定义值类型时,重写 <link tabindex="" keywords="M:System.ValueType.GetHashCode"> 和 <link tabindex="" keywords="M:System.ValueType.Equals(System.Object)"> 方法。如果未重写它们,则运行库会在基 <link tabindex="" keywords="T:System.ValueType"> 类中使用这些方法的普通版本。
-
谨慎使用映射。出于调研目的将映射与非实例化类一起使用会影响应用程序中的实例化对象的性能。
-
确保 RESX 文件中的托管资源具有完全限定名,并且这些资源准确无误。它们必须具有正确的版本和 PublicKeyToken 字段。为未正确指定的类型查找最合适的替代类型会影响性能。
-
请注意,在某些情况下,直接从文件读取应用程序数据就足够了,这比使用 <link tabindex="" keywords="T:System.Resources.ResourceManager"> 效率更高。ResourceManager 可以在定位您的二进制资源之前在文件系统中探测多个位置来查找最匹配的附属程序集。为作业使用适当的工具。
原文出处:http://msdn2.microsoft.com/zh-cn/library/1766918e(VS.80).aspx