一起谈.NET技术,Silverlight的多线程能力(上)

  对于多线程其实一直以来都存在很多误区:比如多任务与多线程就很容易被混为一谈,而多线程也常被理所应当的认为是并行等等。而事实却是:多任务≠多线程、单任务≠单线程、多线程不一定并行,多线程与性能不成线性关系等等,其中道理在这里不再详述。笔者认为Silverlight多线程主要作用不是在于提高性能,而是在于用户体验,其根本目的是解决用户体验中的响应速度,减少单线程带来的阻塞问题。用一个贴切的例子来形容单线程和多线程的区别:单线程就好像只有一个服务窗口卖票的车站,人们排队买票时都是单线程处理的,而且不能抢夺位置,这样只要前方有一个人出现长时间等待,后面的人都不能被响应,这就出现了单线程阻塞;而多线程就好像有多个服务窗口去卖票,这样车票买卖和等待的情况就会好很多(当然这个例子如果换成公共厕所,对于用户体验就显得更为重要了)。

  这次我们就要来看看Silverlight的多线程能力,其实Silverlight的多线程体现在两大方面:

  第一方面是将UI线程与后台工作线程的分离,使得UI线程可以更好地响应用户操作,而后台线程处理完后,允许通过异步的方式将处理结果推回前台进行展示。笔者认为这是多线程在Silverlight中最主要的作用(很多传统Web应用开发者在刚开始接触Silverlight时很不适应这种前后台线程的异步操作)。

  第二方面是对后台作业的多线程支持,比如当需要在客户端后台并行运算时,你可以通过发起多个线程来完成这些运算。在上期《Silverlight CoreCLR结构浅析》中,我已经给大家介绍了Silverlight的基础类库,其中就包括多线程的相关类集。

  UI线程是Silverlight与用户交互的线程,在Silverlight中UI线程是单一的,其中装入的是UI控件类及用于数据绑定的View Model类(什么是View Model?就是只为View层服务的实体,如果要展开说会很长,就此打住!),而在后台线程中是不能直接访问这些UI线程中的数据与控件对象的属性。但大家不用担心,Silverlight和WPF的线程模型都使用了类似于Java Swing中EDT(Event Dispatch Thread)这种安全的事件分发线程模型来解决UI线程与其他后台线程的数据互访问题。在Silverlight(WPF)的控件类库System.Windows下所有类都继承了DependencyObject基类,DependencyObject类不仅提供了Silverlight(WPF)最基础的依赖性属性服务(什么是依赖性属性?简单的说就是对象属性值依赖于其他计算值的方式,这种方式为数据绑定、动画、重用样式都提供了可行性,这里不再展开),同时也开启了UI线程与后台线程的数据互访通道,在DependencyObject中有一个非常重要的属性——Dispatcher,后台线程可以通过调用发起者(一般都是UI控件)的Dispatcher来实现互操作,后台线程可以通过下面的方式来直接操作UI线程中的对象:


_UISender.Dispatcher.BeginInvoke(() =>
{
//这里可以访问UI线程中的对象,因为这个委托本身就在UI线程中执行
}

  上面的()=>是Lamda表达式中对于无入参的委托方法的简写形式,如果有传入参数可以在括号中列明,当然你也可以使用Action各种重载到其他地方实现委托过程。

  如果要实现UI线程创建并访问后台线程就更加简单,Silverlight提供了多种创建后台线程的方式:

  • 基于普通的System.Threading.Thread类创建后台线程

Thread类是最基础的多线程类,它可以创建一个独立运行的线程,比如:


Threadthread = newThread(obj.functionName);
thread.IsBackground = true;
thread.Start();

但Thread对于线程的监控、销毁、回调都比较复杂,因此笔者往往使用Thread来完成一些简单的且不需要回调的任务。

基于System.Threading.DispatchTimer类创建后台定时器线程

DispatchTimer类是Silverlight(WPF)里才出现的后台线程定时器,相较于原有System.Threading.Timer差别在于DispatchTimer是真正的在后台线程内独立执行,而Timer仍然在UI线程中执行,只是定时获得UI线程控制权而已。DispatchTimer只适合于定时执行的任务,你可以根据需要来设置等待时歇,其创建方式如下:


DispatcherTimer dt = newDispatcherTimer();
dt.Interval = newTimeSpan(0, 0, 0, 0, 10);
dt.Tick += newEventHandler(dt_Tick);
dt.Start();
void dt_Tick(object sender, EventArgs e)
{
//超过等待时歇时发生
//这里可以访问UI线程中的对象
//如果要结束定时器可以调用dt.Stop();
}

DispatcherTimer其实也是除StoryBoard外可以实现动画的重要组件,当然要慎用DispatcherTimer来构建过多后台线程,否则会使CPU调度开销增加反而影响效率!(调度开销将在下部分讲解)

基于System.ComponentModel.BackgroundWorker类轻松创建后台线程

微软在WinForm架构中就引入了BackgroundWorker类,这个类内建了许多线程包装方法,从而大大简化线程交互的编码过程。在Silverlight(WPF)中也可以通过BackgroundWorker类来轻松创建后台线程,其创建方式如下:


BackgroundWorker bw = newBackgroundWorker();
bw.DoWork += newDoWorkEventHandler((object, doworkeventarg) =>obj.function());
bw.RunWorkerCompleted += newRunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
if(!bw.IsBusy) bw.RunWorkerAsync();
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//任务完成时回调事件
}

BackgroundWorker也可以通过ReportProgress(intpercentProgress)方法来向其他线程报告其进度完成情况,当然这只适合于可量化进度的后台工作线程,其实现如下:


//后台线程obj.function()中

obj.ReportProgress(i);

//在UI线程中定义报告时间委托
bw.ProgressChanged += newProgressChangedEventHandler(bw_ProgressChanged);
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//显示进度的相关处理方法
}

  • 基于System.Threading.ThreadPool静态类创建后台线程

在所有多线程解决方案中,ThreadPool线程池是笔者最常用的技术。其优点在于易于控制并且减少开销,在线程池中的线程不会由于完成一个任务就消亡,而是会继续执行其他的任务,大大减少了线程的创建与销毁开销。ThreadPool中的QueueUserWorkItem方法可以将任何处理函数排入后台线程队列中执行,其创建方式也非常简单:


obj.OnEvent += (object, eventarg) => Dispatcher.BeginInvoke(UI_OnEvent);
ThreadPool.QueueUserWorkItem(state =>obj.function(), stat);
voidUI_OnEvent()
{
//后台线程事件发生时的回调事件
}

后台线程对象obj中你可以随意定义回调事件,并通过Dispatcher.BeginInvoke的方法来通知UI线程的委托。这样的方式比较简单而且实用。当然ThreadPool类还提供了RegisterWaitForSingleObject方法来实现Timer定时器的功能,可以说ThreadPool是在企业应用中比较常用的多线程实现类。

  至此,就给大家介绍了Silverlight常用多线程实现方式,但笔者还要强调的是:Silverlight的多线程是为了提升用户体验。其实Silverlight开发围绕的关键是用户体验,用户体验在现代商业应用开发中的地位非常的重要。本主题的下半部分,笔者将通过一个实例来为大家讲述Silverlight的多线程性能,以及与其他Web开发技术的性能对比。

时间: 2024-09-09 07:44:50

一起谈.NET技术,Silverlight的多线程能力(上)的相关文章

一起谈.NET技术,Silverlight 的多线程能力(下)

上一期笔者介绍了Silverlight实现多线程的诸多解决方案,本期笔者将通过一个实例来实现所有多线程编程方法,并且还将于JavaScript和Flash两种Web客户端技术性能进行比较,请勿拍砖. 在正式编程前,笔者还要重申上期非常重要的观点:Silverlight多线程主要作用不是在于提高性能,而是在于用户体验.这里要给多线程泼一盆冷水了,多线程与性能提升不是正比关系,如果你使用一个单核CPU的客户端设备,那么即便你创建100个多线程也与单线程的计算性能是一样的,因为一个CPU时间片下只能处

Silverlight 的多线程能力(下“.NET技术”)

上一期笔者介绍了Silverlight实现多线程的诸多解决方案,本期笔者将通过一个实例来实现所有多线程编程方法,并且还将于JavaScript和Flash两种Web客户端技术性能进行比较,请勿拍砖. 在正式编程前,笔者还要重申上期非常重要的观点:Silverlight多线程主要作用不是在于提高性能,而是在于用户体验.这里要给多线程泼一盆冷水了,多线程与性能提升不是正比关系,如果你使用一个单核CPU的客户端设备,那么即便你创建100个多线程也与单线程的计算性能是一样的,因为一个CPU时间片下只能处

一起谈.NET技术,闲话“多线程”

一,摘要         圣殿骑士首先向大家说声对不起,由于最近身体不适,同时也因为这些天一直在研究微软的云计算平台Windows Azure(公司项目需要),所以暂停了更新WPF 基础到企业应用系列索引,不过经过这几天的调节,尤其是到海边去晒了晒太阳,现在又开始继续发文了,大家有兴趣也可以去看看漂亮的大海图片工作之余的闲暇,今天这篇文章不是专业谈多线程,只是应一些朋友的要求对上篇文章WPF 基础到企业应用系列4--WPF千年轮回进行一些额外的补充,如果有时间,可以单独写一个专题来详细深入多线程

一起谈.NET技术,.NET多线程的探讨

本文开始总结.NET下的多种多线程机制,不断更新中,往各位补充.  Invoke机制 最近在实验一个webservice时候,想到了要用异步机制,于是好好研究了一下多线程和Invoke机制,这里写点小小的心得,如有不妥,请各位指教. 我们往往会遇到这样的需求:有一个十分耗时间的工作(比如一个WebSerive的请求),我们不希望它阻塞现有的UI线程(因为这样会导致界面假死),而是希望它在另外一个线程里面执行,并在执行完毕之后将结果"通知"UI线程.这个需求需要通过Invoke和委托

Silverlight“.NET研究” 的多线程能力(下)

上一期笔者介绍了Silverlight实现多线程的诸多解决方案,本期笔者将通过一个实例来实现所有多线程编程方法,并且还将于JavaScript和Flash两种Web客户端技术性能进行比较,请勿拍砖. 在正式编程前,笔者还要重申上期非常重要的观点:Silverlight多线程主要作用不是在于提高性能,而是在于用户体验.这里要给多线程泼一盆冷水了,多线程与性能提升不是正比关系,如果你使用一个单核CPU的客户端设备,那么即便你创建100个多线程也与单线程的计算性能是一样的,因为一个CPU时间片下只能处

Silver“.NET研究”light的多线程能力(上)

对于多线程其实一直以来都存在很多误区:比如多任务与多线程就很容易被混为一谈,而多线程也常被理所应当的认为是并行等等.而事实却是:多任务≠多线程.单任务≠单线程.多线程不一定并行,多线程与性能不成线性关系等等,其中道理在这里不再详述.笔者认为Silverlight多线程主要作用不是在于提高性能,而是在于用户体验,其根本目的是解决用户体验中的响应速度,减少单线程带来的阻塞问题.用一个贴切的例子来形容单线程和多线程的区别:单线程就好像只有一个服务窗口卖票的车站,人们排队买票时都是单线程处理的,而且不能

一起谈.NET技术,WPF/Silverlight深度解决方案:目录

介于目前WPF/Silverlight技术资料在国内相当稀缺,仅有的也是一些很基础的教程.为了更深度的剖析WPF/Silverlight的技术内涵,解决开发过程中的疑难杂症,分解实际应用案例的特色细节,"WPF/Silverlight深度解决方案"系列由此孕育而生.整个系列的所有文章均为原创,由本人的个人开发经验结合相关资料编写而成,过程中难免有错漏或不妥当的地方还望各位读者友善的指出.我们的目标只有一个:WPF/Silverlight技术深度挖掘.如果您有符合本系列主题的内容想要与大

一起谈.NET技术,Silverlight与HTML双向交互

Silverlight具备很好的用户体验,但有时需要在页面的布局上进行特殊处理,比如作为webpart集成到Sharepoint中等等. HTML和Silverlight之间的双向交互可以更灵活的使用Silverlight进行开发,上午摸索了一下,记录在此. 一,向Silverlight传递数据,实现个性化加载 Silverlight在HTML中的引用是: <object data="data:application/x-silverlight-2," type="ap

一起谈.NET技术,大话Session

引言     在web开发中,session是个非常重要的概念.在许多动态网站的开发者看来,session就是一个变量,而且其表现像个黑洞,他只需要将东西在合适的时机放进这个洞里,等需要的时候再把东西取出来.这是开发者对session最直观的感受,但是黑洞里的景象或者说session内部到底是怎么工作的呢?当笔者向身边的一些同事或朋友问及相关的更进一步的细节时,很多人往往要么含糊其辞要么主观臆断,所谓知其然而不知其所以然. 笔者由此想到很多开发者,包括我自己,每每都是纠缠于框架甚至二次开发平台之