关于Silverlight中的多线程的理解

这段时间由于Silverlight的性能问题导致我们之前的项目客户很不满意,并要求整改,所以开始研究了一些性能相关的内容,其中一个就是Silverlight的线程模型是怎样的。把我自己从测试以及其他人的文章中得出的理解分享一下,有不对的地方也请指正啦:

一条很重要的认识是,Silverlight只有一个主线程,也就是我们常说的UI线程。

第二条是这个主线程实际上负责很多的事情,例如,处理用户输入,呈现页面,运行动画等等。

这两条认识之所以重要,是因为它们会使我们对很多Silverlight中遇到的问题有深刻地理解,这里举几个例子说明一下。

1. 关于同步调用WCF问题的理解:

这里大家都熟悉的是异步调用WCF,之所以说成同步,是因为我们可能都有这样的需求,当我们调用一个WCF方法时发现,它依赖于之前调用的WCF方法的返回值。但是当我们尝试使用Windows Form开发中使用的多线程知识处理时(即阻止线程以等待另一个线程返回结果)发现,页面会被卡死。

对于这个问题的原因就是我们对于Silverlight的主线程没有很好地理解。其实我们在xaml代码页面里编写的大部分都是由主线程执行的,所以当我们正常在方法里阻止当前线程时,实际上阻止的是主线程(UI线程),这就是为什么卡死的原因了;另外要注意的是,异步调用WCF,实际是当主线程执行完一个方法或事件处理方法后,处于空闲状态时才会触发一个子线程去真正调用WCF方法。

由此一种解决方法是,开一个子线程去调用WCF方法,并在Completed事件处理方法里阻止当前线程,然后使用主线程或另外的子线程调用另一个WCF方法,并在这个方法的Completed事件处理方法里释放被阻止的线程,此时就可以达到同步的效果了。

2.关于在DataGrid控件里显示大数据量很慢问题的理解:

当需求里不希望使用分页进行显示大数量时,我们的代码就会遇到很大的性能问题。例如,在DataGrid控件里显示10万条数据,呵呵,可想而知,不卡都怪了。估计你在想,这和UI线程有什么关系呢?问题的在于绑定,因为通常我们将数据绑定到DataGrid上。

当Silverlight从服务端获取10万条数据后,这里不考虑网络传输和服务端处理所消耗的时间,只专注于Silverlight的部分,会将结果集放到数据集合里(如ObservableCollection),然后绑定到DataGrid控件上。由于Silverlight不允许跨线程访问UI控件的限制,这就导致不管你是使用子线程,还是使用UI线程填充集合,UI线程都要等待填充完毕后才能绑定到DataGrid控件上。这里Silverlight是有优化的,因为DataGrid控件默认启用UI虚拟化技术,只会绑定可见的行,这大大减少了显示时间,但是向集合里填充10万条数据就成为主要耗时部分。

对此的一种解决方法就是,向集合里填充部分数据,而不是一次性将10万数据都装载进去。服务端的具体做法不变,只是在DataGrid控件的LoadingRow事件里判断一下是否已经到浏览的底部,这里假设每页200条数据,这样使用e.Row.GetIndex()方法判断是否等于页数*200,如果成立,就调用下一页的数据。

以上只是一个思路,具体的情况需要和需求一致,不过这两个认识确实能给我们理解Silverlight的线程架构带来很大的帮助。希望对大家有所帮助,同时如果有不准确的地方也希望指出来,共同学习。

这篇博客也指出了一些这样的认识,并且说明了Silverlight5中对其进行的有限的改进,如果有兴趣的朋友可以看看。

你可能感兴趣的:(Silverlight)