提高silverlight 的渲染速度
如果你的silverlight 需要渲染大量的UI对象,你或许得为silverlight的渲染速度而忧虑。
如果你的UI对象还绑定一个复杂的数据实体,那么你会为silverlight的渲染速度而抓狂。这究竟这是silverlight 这个东东本身的缺陷还是我们无意触碰了潘多拉的魔盒?
我曾经用微软官方提供的一个silverlight树控件来绘制一个六百多个节点的指标树,为了让代码看上去很美,大量利用了silverlight 的一些特性,例如数据绑定,视觉状态,在xaml中进行数据转换,等等,但是很不幸,结果是树要同时展开一级节点的时候,需要停顿(UI失去响应)估计1s.由于客户需要一个全部展开的功能以方便他更好的浏览这些指标就像他观察股市波动一样去了解他的公司运营情况,结果等待的时间估计得让人抓狂。
为了提高silverlight 的渲染性能,以下是微软官方给的一些建议:
- 谨慎对 Silverlight 插件使用透明背景
- 对 UIElement 的不透明度或转换进行动画处理时设置其 CacheMode
- 对文本进行动画处理时将 TextRenderingMode 设置为 RenderForAnimation
- 将使用不透明度对象和旋转或拉伸对象的层混合时缓存可视元素
- 避免使用无窗口模式
- 尽可能使用 Visibility 而不是 Opacity
- 在全屏模式下隐藏未使用的对象
- 不要将 Width 和 Height 与 MediaElement 对象一起使用
- 不要将 Width 和 Height 与 Path 对象一起使用
- 将占用 CPU 资源较多的任务分解为较小的任务
- 分解非常大的应用程序包
- 使用 Double.ToString(CultureInfo.InvariantCulture) 而不是 Double.ToString()
- 呈现大量图像时使用 Stretch="Fill"。
经过测试,的确能对性能有一定提升,然而,对于UI的渲染速度,效果并不理想。考虑到
Silverlight对xaml访问的速度要明显慢于托管代码,那么问题估计就出现在这里了。
当你按照微软官方建议优化完你的代码,你可以通过下面介绍的方式进一步提升silverlight 的界面渲染速度(更准确的应该称为界面响应速度)。
1、 减轻你程序中xaml的负担。如果不是程序的必须,请你尽量不要使用数据绑定,数据转换器等功能。
关于这一点也许你与我争论,因为数据绑定这正是silverlight的亮点之一,你却摒弃它,天理不容啊。
这里我并不想与你用某某理论争论,用一些例子来说明似乎更有说服力。附件附近是我做的一个小程序,程序分别用普通方式(简单数据赋值)、数据绑定方式,以及自定义控件(简单数据赋值),创建一定数据的对象(三种方式的UI对象完全一样),并跟踪了不同情况UI响应时间,差异非常巨大。请看一下表格:
渲染1000个个体的时间对比(单位:毫秒):
|
次数 |
普通赋值(用户控件) |
数据绑定(用户控件) |
普通赋值(自定义控件) |
|
1 |
828.125 |
1781.25 |
953.125 |
|
2 |
843.75 |
1734.375 |
984.375 |
|
3 |
828.125 |
1734.375 |
953.125 |
|
4 |
1250 |
1750 |
906.25 |
|
5 |
843.75 |
1734.375 |
937.5 |
|
平均 |
918.75 |
1746.875 |
946.875 |
渲染2000个UI个体的时间对比(单位:毫秒)
|
次数 |
普通赋值(用户控件) |
数据绑定(用户控件) |
普通赋值(自定义控件) |
|
1 |
1984.375 |
3796.875 |
2328.125 |
|
2 |
1859.375 |
4734.375 |
2453.125 |
|
3 |
1828.125 |
4859.375 |
2531.25 |
|
4 |
1859.39 |
3656.25 |
2843.75 |
|
5 |
2015.625 |
3718.75 |
2656.25 |
|
平均 |
1909.375 |
4153.125 |
2562.5 |
|
|
|
|
|

不难看出,结果证明这么一个理论:越是简单的方式,效率越高。这样做付出的代价就是程序代码不那么美观,但是如果你的程序设计的合理,这不应该成为你程序难以维护的借口。
2、 利用后台线程或和线程池减轻UI线程的负担。
建议你将与UI无关的逻辑统统让后台线程去执行,以提高用户的体验。这里给出一个模板,供你参考:
public void BindTree()
{
//这里是数据逻辑,以提供渲染UI所需的参数
ThreadPool.QueueUserWorkItem(new WaitCallback(InnerBind), argument);
}
public void InnerBind(object argument)
{
//这里是你的数据逻辑
this.treeView.Dispatcher.BeginInvoke(delegate
{
//这里是你的UI逻辑
});
}
3、 UI界面元素的简单性。
例如:如果你只是要想实现一个简单的button的功能,建议你不要使用Button控件,你完全何以使用一个border来代替,一个实例化后的Button有九十多个属性(包括事件等),而你却只需要一两个属性或事件,这显然是一种浪费。
4、 正确存放资源。
有些资源仅仅是在某个命名空间下的几个元素使用,就不需要把它放到app里面,这样对初始化加载有很大好处,而 且 使用该资源的对象去查询该资源也会更加快速。

浙公网安备 33010602011771号