技术开发 频道

Silverlight 4中五种多线程编程技巧

  清单4:

       void DoWork(object sleepMillisecond)

  {

  Dispatcher.BeginInvoke((ThreadStart) delegate()

  {

  button1.Content
= "Hello world!";

  });

  
//省略其他内容……

  }

  再次运行上面的代码,你会发现Button控件的Content属性值已修改成功。要获得一个更加模块化的设计风格,也可以如下表达相同的功能:

  清单5:

void DoWork(object sleepMillisecond)

  {

  Dispatcher.BeginInvoke(ChangeIt);

  
//省略其他内容……

  }

  
private void ChangeIt()

  {

  button1.Content
= "Hello world!";

  }

  正如你在其他许多的框架中所看到的,Silverlight线程也分为两类:用户界面线程和工作者线程。Silverlight的UI线程是与用户进行交互的线程。在UI线程中,专门设计了一些用户界面控件类和视图模型(ViewModel)类用于实现数据绑定。根据Silverlight设计框架的规定,后台工作线程不能直接访问UI线程的数据对象和控件中的属性。但是,你也没有必要为此过于担心。Silverlight中的线程模型中已经提供了一个安全的基于事件的调度器(dispatcher)模型,它类似于Java Swing中的EDT(事件调度线程)。借助于这种事件调度器机制,我们也可以轻松完成UI线程和后台工作线程之间的数据交互。

  我们知道,所有Silverlight控件都继承于DependencyObject这个基类。值得注意是,DependencyObject类不仅为Silverlight提供了基本的依赖性服务,也开启了一条UI线程和后台工作线程之间的数据交互的通道。DependencyObject具有一个非常重要的属性-Dispatcher。因此,后台线程可以调用发射器(主要是UI控件)的Dispatcher对象来实现上述数据交互之目的。下面举例说明一个使用这种机制的典型的操作模式:

  清单6:

_UISender.Dispatcher.BeginInvoke(() =>

  {

  
//我们可以在此访问UI线程中的对象,因为代理本身是在UI线程的上下文中执行的

  }

  上述()=>是一个lambda表达式,这是一种没有传入参数的委托方法的缩写形式。如果有传入的参数的话,我们可以将其在括号中指定。

  3.使用Deployment.Current.Dispatcher

  截至目前,上面提供的示例都是在UI控件已经启动的前提下进行的。正如我们所知道的,一般情况下Application.Current.RootVisual.Dispatcher属性引入的目的主要用于检索一个应用程序的System.Windows.Threading.Dispatcher。但是,如果在RootVisual创建之前这种操作是不会得到支持的。为了在创建RootVisual之前获得应用程序的一个调度器Dispatcher,我们可以借助于System.Windows.Deployment.Current.Dispatcher对象。

0
相关文章