WPF Dispatcher在界面操作中作用体现

开发 开发工具
WPF Dispatcher作为一个在界面操作和更新时被UI线程关联的唯一对象,起了一个非常重要的作用。他可以帮助我们实现按序排列的工作项队列。

对于一个开发人员来说,可能在开发一个程序的时候对图形界面的要求并不是很高,因为他们不是美工。那么,使用了WPF后,开发人员可以轻松的实现精美的图形界面。#t#

使用一个专用的 UI 线程来完成界面的操作和更新,这个线程会关联一个***的WPF Dispatcher 对象,用于调度按优先顺序排列的工作项队列。Application.Run() 实际上就是对 Dispatcher.Run() 的间接调用。

WPF Dispatcher通过循环来处理工作项队列,这个循环通常被成为 "帧 (DispatcherFrame)"。Dispatcher.Run() 创建并启动这个帧,这也是 Application.Run() 启动消息循环的最终途径。

 

  1. public sealed class Dispatcher  
  2. {  
  3. [SecurityCritical, 
    UIPermission(SecurityAction.
    LinkDemand, 
    Unrestricted=true)]  
  4. public static void Run()  
  5. {  
  6. PushFrame(new DispatcherFrame());  
  7. }  

 

DispatcherFrame 可以嵌套,并通过检查 Continue 属性来决定循环是否继续。我们可以通过调用 Dispatcher.ExitAllFrames() 来终止所有的帧循环,当然这种编程方式并不可取,可能会造成一些意外出现。

与WPF Dispatcher调度对象想对应的就是 DispatcherObject,在 WPF 中绝大部分控件都继承自 DispatcherObject,甚至包括 Application。这些继承自 DispatcherObject 的对象具有线程关联特征,也就意味着只有创建这些对象实例,且包含了 Dispatcher 的线程(通常指默认 UI 线程)才能直接对其进行更新操作。

当我们尝试从一个非 UI 线程更新一个标签,会看到一个如下的异常。

 

  1. private void button1_Click
    (object sender, RoutedEventArgs e)  
  2. {  
  3. new Thread(() => this.label1.
    Content
     = DateTime.Now.
    ToString()).Start();  

 

 

按照 DispatcherObject 的限制原则,我们改用 Window.Dispatcher.Invoke() 即可顺利完成这个更新操作。

 

  1. private void button1_Click
    (object sender, Routed
    EventArgs e)  
  2. {  
  3. new Thread(() => 
  4. {  
  5. this.Dispatcher.Invoke
    (DispatcherPriority.Normal,  
  6. new Action(() => this.
    label1.Content
     = DateTime.
    Now.ToString()));  
  7. }).Start();  

 

如果在其他项目(比如类库)中,我们可以用 Application.Current.Dispatcher.Invoke(...) 完成同样的操作,它们都指向 UI Thread Dispatcher 这个***对象。

WPF Dispatcher还提供了 BeginInvoke 这个异步版本。

 

  1. private void button1_Click(object 
    sender, RoutedEventArgs e)  
  2. {  
  3. new Thread(() => 
  4. {  
  5. Application.Current.Dispatcher.
    BeginInvoke(DispatcherPriority.Normal,  
  6. new Action(() => 
  7. {  
  8. Thread.Sleep(3000);  
  9. this.label1.Content = 
    DateTime.Now.ToString();  
  10. }));  
  11. MessageBox.Show("Hi!");  
  12. }).Start();  

 

凡事都有例外,WPF 还提供了一种继承自 Freezable 的类型,尽管 Freezable 也间接继承自 DispatcherObject,但当诸如WPF Dispatcher这类对象从修改状态变成冻结状态时,它即变成自由线程对象,不在具有线程关联。

责任编辑:曹凯 来源: 开发学院
相关推荐

2009-12-24 17:52:05

WPF触发器

2009-12-29 14:58:31

WPF优点

2009-12-28 09:50:08

WPF数据绑定

2024-03-15 09:44:17

WPFDispatcherUI线程

2009-12-25 15:29:12

WPF缺陷

2010-02-02 13:15:00

C++ lambda函

2010-02-25 17:22:39

WCF服务行为

2009-12-04 17:31:32

PHP编码转换

2010-01-14 10:35:34

VB.NET指针

2009-12-25 16:40:49

WPF优势

2009-08-31 16:49:23

WPF线程模型

2010-01-08 18:02:33

VB.NET事件

2010-01-15 13:30:53

VB.NET Tool

2010-01-19 15:21:55

VB.NET区域性

2010-01-14 13:27:33

VB.NET操作符li

2010-02-23 16:15:24

WCF Endpoin

2009-12-28 16:45:31

WPF窗体

2010-01-20 18:34:46

VB.NET Syst

2009-12-02 13:16:32

PHP DOMXPat

2009-12-28 17:48:01

WPF界面布局
点赞
收藏

51CTO技术栈公众号