(转)WPF性能优化点 http://www.cnblogs.com/YilingLai/archive/2007/01/19/624714.html
2008-10-21 19:58
465 查看
在建立漂亮UI的同时,我们还需要关注应用程序的性能,WPF尤其如此。下面从MS的文档中总结出了一些有用的性能优化点。在实际编写的过程中,可以参考。这个Post非完全原创,是根据一些文档总结出来的。
1、建立逻辑树的时候,尽量考虑从父结点到子结点的顺序构建。因为当逻辑树的一个结点发生变化时(比如添加或删除),它的父结点和所有的子结点都会激发Invalidation。我们应该避免不必要的Invalidation。
2、当我们在列表(比如ListBox)显示了一个CLR对象列表(比如List)时,如果想在修改List对象后,ListBox也动态的反映这种变化。此时,我们应该使用动态的ObservableCollection对象绑定。而不是直接的更新ItemSource。两者的区别在于直接更新ItemSource会使WPF抛弃ListBox已有的所有数据,然后全部重新从List加载。而使用ObservableCollection可以避免这种先全部删除再重载的过程,效率更高。
3、在使用数据绑定的过程中,如果绑定的数据源是一个CLR对象,属性也是一个CLR属性,那么在绑定的时候对象CLR对象所实现的机制不同,绑定的效率也不同。
A、数据源是一个CLR对象,属性也是一个CLR属性。对象通过TypeDescriptor/PropertyChanged模式实现通知功能。此时绑定引擎用TypeDescriptor来反射源对象。效率最低。
B、数据源是一个CLR对象,属性也是一个CLR属性。对象通过INotifyPropertyChanged实现通知功能。此时绑定引擎直接反射源对象。效率稍微提高。
C、数据源是一个DependencyObject,而且属性是一个DependencyProperty。此时不需要反射,直接绑定。效率最高。
4、访问CLR对象和CLR属性的效率会比访问DependencyObject/DependencyProperty高。注意这里指的是访问,不要和前面的绑定混淆了。但是,把属性注册为DependencyProperty会有很多的优点:比如继承、数据绑定和Style。所以有时候我们可以在实现DependencyProperty的时候,利用缓存机制来加速访问速度:看下面的缓存例子:
public static readonly DependencyProperty MagicStringProperty =
DependencyProperty.Register("MagicString", typeof(string), typeof(MyButton), new PropertyMetadata(new PropertyInvalidatedCallback(OnMagicStringPropertyInvalidated),new GetValueOverride(MagicStringGetValueCallback)));
private static void OnMagicStringPropertyInvalidated(DependencyObject d)
{
// 将缓存的数据标识为无效
((MyButton)d)._magicStringValid = false;
}
private static object MagicStringGetValueCallback(DependencyObject d)
{
// 调用缓存的访问器来获取值
return ((MyButton)d).MagicString;
}
// 私有的CLR访问器和本地缓存
public string MagicString
{
get
{
// 在当前值无效时,获取最新的值保存起来
if (!_magicStringValid)
{
_magicString = (string)GetValueBase(MagicStringProperty);
_magicStringValid = true;
}
return _magicString;
}
set
{
SetValue(MagicStringProperty, value);
}
}
private string _magicString;
private bool _magicStringValid;
另外,因为注册的DependencyProperty在默认是不可继承的,如果需要继承特性,也会降低DependencyProperty值刷新的效率。注册DependencyProperty属性时,应该把DefaultValue传递给Register方法的参数来实现默认值的设置,而不是在构造函数中设置。
5、使用元素TextFlow和TextBlock时,如果不需要TextFlow的某些特性,就应该考虑使用TextBlock,因为它的效率更高。
6、在TextBlock中显式的使用Run命令比不使用Run命名的代码要高。
7、在TextFlow中使用UIElement(比如TextBlock)所需的代价要比使用TextElement(比如Run)的代价高。
8、把Label(标签)元素的ContentProperty和一个字符串(String)绑定的效率要比把字符串和TextBlock的Text属性绑定的效率低。因为Label在更新字符串是会丢弃原来的字符串,全部重新显示内容。
9、在TextBlock块使用HyperLinks时,把多个HyperLinks组合在一起效率会更高。看下面的两种写法,后一种效率高。
A、
<TextBlock Width="600" >
<Hyperlink TextDecorations="None">MSN Home</Hyperlink>
</TextBlock>
<TextBlock Width="600" >
<Hyperlink TextDecorations="None">My MSN</Hyperlink>
</TextBlock>
B、
<TextBlock Width="600" >
<Hyperlink TextDecorations="None">MSN Home</Hyperlink>
<Hyperlink TextDecorations="None">My MSN</Hyperlink>
</TextBlock>
10、任与上面TextDecorations有关,显示超链接的时候,尽量只在IsMouseOver为True的时候显示下划线,一直显示下划线的代码高很多。
11、在自定义控件,尽量不要在控件的ResourceDictionary定义资源,而应该放在Window或者Application级。因为放在控件中会使每个实例都保留一份资源的拷贝。
12、如果多个元素使用相同的Brush时,应该考虑在资源定义Brush,让他们共享一个Brush实例。
13、如果需要修改元素的Opacity属性,最后修改一个Brush的属性,然后用这个Brush来填充元素。因为直接修改元素的Opacity会迫使系统创建一个临时的Surface。
14、在系统中使用大型的3D Surface时,如果不需要Surface的HitTest功能,请关闭它。因为默认的HitTest会占用大量的CPU时间进行计算。UIElement有应该IsHitTestVisible属性可以用来关闭HitTest功能。
1、建立逻辑树的时候,尽量考虑从父结点到子结点的顺序构建。因为当逻辑树的一个结点发生变化时(比如添加或删除),它的父结点和所有的子结点都会激发Invalidation。我们应该避免不必要的Invalidation。
2、当我们在列表(比如ListBox)显示了一个CLR对象列表(比如List)时,如果想在修改List对象后,ListBox也动态的反映这种变化。此时,我们应该使用动态的ObservableCollection对象绑定。而不是直接的更新ItemSource。两者的区别在于直接更新ItemSource会使WPF抛弃ListBox已有的所有数据,然后全部重新从List加载。而使用ObservableCollection可以避免这种先全部删除再重载的过程,效率更高。
3、在使用数据绑定的过程中,如果绑定的数据源是一个CLR对象,属性也是一个CLR属性,那么在绑定的时候对象CLR对象所实现的机制不同,绑定的效率也不同。
A、数据源是一个CLR对象,属性也是一个CLR属性。对象通过TypeDescriptor/PropertyChanged模式实现通知功能。此时绑定引擎用TypeDescriptor来反射源对象。效率最低。
B、数据源是一个CLR对象,属性也是一个CLR属性。对象通过INotifyPropertyChanged实现通知功能。此时绑定引擎直接反射源对象。效率稍微提高。
C、数据源是一个DependencyObject,而且属性是一个DependencyProperty。此时不需要反射,直接绑定。效率最高。
4、访问CLR对象和CLR属性的效率会比访问DependencyObject/DependencyProperty高。注意这里指的是访问,不要和前面的绑定混淆了。但是,把属性注册为DependencyProperty会有很多的优点:比如继承、数据绑定和Style。所以有时候我们可以在实现DependencyProperty的时候,利用缓存机制来加速访问速度:看下面的缓存例子:
public static readonly DependencyProperty MagicStringProperty =
DependencyProperty.Register("MagicString", typeof(string), typeof(MyButton), new PropertyMetadata(new PropertyInvalidatedCallback(OnMagicStringPropertyInvalidated),new GetValueOverride(MagicStringGetValueCallback)));
private static void OnMagicStringPropertyInvalidated(DependencyObject d)
{
// 将缓存的数据标识为无效
((MyButton)d)._magicStringValid = false;
}
private static object MagicStringGetValueCallback(DependencyObject d)
{
// 调用缓存的访问器来获取值
return ((MyButton)d).MagicString;
}
// 私有的CLR访问器和本地缓存
public string MagicString
{
get
{
// 在当前值无效时,获取最新的值保存起来
if (!_magicStringValid)
{
_magicString = (string)GetValueBase(MagicStringProperty);
_magicStringValid = true;
}
return _magicString;
}
set
{
SetValue(MagicStringProperty, value);
}
}
private string _magicString;
private bool _magicStringValid;
另外,因为注册的DependencyProperty在默认是不可继承的,如果需要继承特性,也会降低DependencyProperty值刷新的效率。注册DependencyProperty属性时,应该把DefaultValue传递给Register方法的参数来实现默认值的设置,而不是在构造函数中设置。
5、使用元素TextFlow和TextBlock时,如果不需要TextFlow的某些特性,就应该考虑使用TextBlock,因为它的效率更高。
6、在TextBlock中显式的使用Run命令比不使用Run命名的代码要高。
7、在TextFlow中使用UIElement(比如TextBlock)所需的代价要比使用TextElement(比如Run)的代价高。
8、把Label(标签)元素的ContentProperty和一个字符串(String)绑定的效率要比把字符串和TextBlock的Text属性绑定的效率低。因为Label在更新字符串是会丢弃原来的字符串,全部重新显示内容。
9、在TextBlock块使用HyperLinks时,把多个HyperLinks组合在一起效率会更高。看下面的两种写法,后一种效率高。
A、
<TextBlock Width="600" >
<Hyperlink TextDecorations="None">MSN Home</Hyperlink>
</TextBlock>
<TextBlock Width="600" >
<Hyperlink TextDecorations="None">My MSN</Hyperlink>
</TextBlock>
B、
<TextBlock Width="600" >
<Hyperlink TextDecorations="None">MSN Home</Hyperlink>
<Hyperlink TextDecorations="None">My MSN</Hyperlink>
</TextBlock>
10、任与上面TextDecorations有关,显示超链接的时候,尽量只在IsMouseOver为True的时候显示下划线,一直显示下划线的代码高很多。
11、在自定义控件,尽量不要在控件的ResourceDictionary定义资源,而应该放在Window或者Application级。因为放在控件中会使每个实例都保留一份资源的拷贝。
12、如果多个元素使用相同的Brush时,应该考虑在资源定义Brush,让他们共享一个Brush实例。
13、如果需要修改元素的Opacity属性,最后修改一个Brush的属性,然后用这个Brush来填充元素。因为直接修改元素的Opacity会迫使系统创建一个临时的Surface。
14、在系统中使用大型的3D Surface时,如果不需要Surface的HitTest功能,请关闭它。因为默认的HitTest会占用大量的CPU时间进行计算。UIElement有应该IsHitTestVisible属性可以用来关闭HitTest功能。
相关文章推荐
- SQL Server性能计数器(转自:http://www.cnblogs.com/netflu/archive/2010/09/22/1832993.html)
- WPF企业内训全程实录(中) 转载 http://www.cnblogs.com/KnightsWarrior/archive/2010/11/01/1866641.html
- 开源性能测试工具 - Apache ab 介绍 ---http://www.cnblogs.com/jackei/archive/2006/07/18/454144.html
- http://www.cnblogs.com/zanxiaofeng/archive/2010/08/27/1810324.html 数据库优化
- SQL优化--使用 EXISTS 代替 IN 和 关联查询(inner join) (转载)http://www.cnblogs.com/zping/archive/2008/08/05/1260959.html
- WPF企业内训全程实录(下) 转载 http://www.cnblogs.com/KnightsWarrior/archive/2010/12/09/1900832.html
- 在测试sql语句性能时先清空缓存【转自:http://www.cnblogs.com/yukaizhao/archive/2008/04/24/1168647.html】
- 性能分析:处理器、磁盘I/O、进程、网络分析方法 http://www.cnblogs.com/fnng/archive/2012/10/30/2747246.html
- 群发UDP的性能测试 (摘自:http://www.cnblogs.com/trywebservice/archive/2008/02/19/1073642.html)
- SQL优化--使用分析函数(转自:http://www.cnblogs.com/zping/archive/2008/08/06/1261973.html)
- 【前端优化】通过六种方法提高网站访问速度 (转http://www.cnblogs.com/fengyin/archive/2011/01/18/1938628.html)
- 关于android性能,内存优化 http://www.cnblogs.com/zyw-205520/archive/2013/02/17/2914190.html
- http://www.cnblogs.com/fengyin/archive/2011/01/18/1938628.html 前端优化
- SD2.0-《Web2.0网站性能调优实践》貌似是抄袭的文章 http://www.cnblogs.com/Duiker/archive/2007/12/03/980936.html
- linux的硬链接与软连接(转载,原文地址为http://www.cnblogs.com/sonic4x/archive/2011/08/05/2128543.html)
- http://www.cnblogs.com/xudong-bupt/archive/2013/12/29/3483059.html
- PHP 杂谈《重构-改善既有代码的设计》之二 对象之间搬移特性【链接:http://www.cnblogs.com/baochuan/archive/2012/04/01/2427199.html】
- C# 实现的多线程异步Socket数据包接收器框架(来源http://www.cnblogs.com/wcfgroup/archive/2008/10/06/1304512.html)
- http://www.cnblogs.com/dajiang02/archive/2011/08/13/2136929.html
- 在IIS上启用Gzip压缩(HTTP压缩) 轉(http://www.cnblogs.com/zhangziqiu/archive/2009/05/17/gzip.html)