WPF 学习笔记 - 2. Dispatcher
[ 2008-08-11 19:13:00 | 作者: yuhen ]
WPF 使用一个专用的 UI 线程来完成界面的操作和更新,这个线程会关联一个唯一的 Dispatcher 对象,用于调度按优先顺序排列的工作项队列。Application.Run() 实际上就是对 Dispatcher.Run() 的间接调用。
Dispatcher 通过循环来处理工作项队列,这个循环通常被成为 "帧 (DispatcherFrame)"。Dispatcher.Run() 创建并启动这个帧,这也是 Application.Run() 启动消息循环的最终途径。
DispatcherFrame 可以嵌套,并通过检查 Continue 属性来决定循环是否继续。我们可以通过调用 Dispatcher.ExitAllFrames() 来终止所有的帧循环,当然这种编程方式并不可取,可能会造成一些意外出现。
与 Dispatcher 调度对象想对应的就是 DispatcherObject,在 WPF 中绝大部分控件都继承自 DispatcherObject,甚至包括 Application。这些继承自 DispatcherObject 的对象具有线程关联特征,也就意味着只有创建这些对象实例,且包含了 Dispatcher 的线程(通常指默认 UI 线程)才能直接对其进行更新操作。
当我们尝试从一个非 UI 线程更新一个标签,会看到一个如下的异常。
按照 DispatcherObject 的限制原则,我们改用 Window.Dispatcher.Invoke() 即可顺利完成这个更新操作。
如果在其他项目(比如类库)中,我们可以用 Application.Current.Dispatcher.Invoke(...) 完成同样的操作,它们都指向 UI Thread Dispatcher 这个唯一对象。
Dispatcher 还提供了 BeginInvoke 这个异步版本。
凡事都有例外,WPF 还提供了一种继承自 Freezable 的类型,尽管 Freezable 也间接继承自 DispatcherObject,但当这类对象从修改状态变成冻结状态时,它即变成自由线程对象,不在具有线程关联。(有关 Freezable 详情可参考 MSDN)
评论Feed: http://www.rainsts.net/feed.asp?q=comment&id=736
Dispatcher 通过循环来处理工作项队列,这个循环通常被成为 "帧 (DispatcherFrame)"。Dispatcher.Run() 创建并启动这个帧,这也是 Application.Run() 启动消息循环的最终途径。
public sealed class Dispatcher
{
[SecurityCritical, UIPermission(SecurityAction.LinkDemand, Unrestricted=true)]
public static void Run()
{
PushFrame(new DispatcherFrame());
}
}DispatcherFrame 可以嵌套,并通过检查 Continue 属性来决定循环是否继续。我们可以通过调用 Dispatcher.ExitAllFrames() 来终止所有的帧循环,当然这种编程方式并不可取,可能会造成一些意外出现。
与 Dispatcher 调度对象想对应的就是 DispatcherObject,在 WPF 中绝大部分控件都继承自 DispatcherObject,甚至包括 Application。这些继承自 DispatcherObject 的对象具有线程关联特征,也就意味着只有创建这些对象实例,且包含了 Dispatcher 的线程(通常指默认 UI 线程)才能直接对其进行更新操作。
当我们尝试从一个非 UI 线程更新一个标签,会看到一个如下的异常。
private void button1_Click(object sender, RoutedEventArgs e)
{
new Thread(() => this.label1.Content = DateTime.Now.ToString()).Start();
}按照 DispatcherObject 的限制原则,我们改用 Window.Dispatcher.Invoke() 即可顺利完成这个更新操作。
private void button1_Click(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
this.Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(() => this.label1.Content = DateTime.Now.ToString()));
}).Start();
}如果在其他项目(比如类库)中,我们可以用 Application.Current.Dispatcher.Invoke(...) 完成同样的操作,它们都指向 UI Thread Dispatcher 这个唯一对象。
Dispatcher 还提供了 BeginInvoke 这个异步版本。
private void button1_Click(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new Action(() =>
{
Thread.Sleep(3000);
this.label1.Content = DateTime.Now.ToString();
}));
MessageBox.Show("Hi!");
}).Start();
}凡事都有例外,WPF 还提供了一种继承自 Freezable 的类型,尽管 Freezable 也间接继承自 DispatcherObject,但当这类对象从修改状态变成冻结状态时,它即变成自由线程对象,不在具有线程关联。(有关 Freezable 详情可参考 MSDN)
[最后修改由 yuhen, 于 2008-08-11 19:22:08]
评论Feed: http://www.rainsts.net/feed.asp?q=comment&id=736
这篇日志没有评论。







