分享

WPF 基础到企业应用系列3——Dispatcher及多线程

 Jcstone 2013-03-05

Dispatcher及多线程

提到这个UI和后台线程交互这个问题,大家都可能在WinForm中遇到过,记得几年前我参加一个外资企业的面试,公司的其中一道题就是说在WinForm 中如何使用后台线程来操作UI,所以对这个问题比较记忆犹新。

WPF线程分配系统提供一个Dispatcher属性、VerifyAccess  和 CheckAccess 方法来操作线程。线程分配系统位于所有 WPF 类中基类,大部分WPF 元素都派生于此类,如下图的Dispatcher类:

image

WPF 应用程序启动后,会有两个线程:

  1. 一个是用来处理UI呈现(处理UI的请求,比如输入和展现等操作)。
  2. 一个用来管理 UI的 (对UI元素及整个UI进行管理)。

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

image
当我们尝试从一个非 UI 线程更新一个UI元素,会看到如下的异常错误。

  XAML代码

<Window x:Class="WPFApplications.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Height="300" Width="300">
<
StackPanel>
<
Label x:Name="lblHello">Hello,World!</Label>
</
StackPanel>
</
Window>
后台代码:
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
Thread thread = new Thread(ModifyUI);
thread.Start();
}

private void ModifyUI()
{
// 模拟一些工作正在进行
Thread.Sleep(TimeSpan.FromSeconds(5));
lblHello.Content = "Hello,Dispatcher";
}
}

错误截图:

image

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

private void ModifyUINew()
{
// 模拟一些工作正在进行
Thread.Sleep(TimeSpan.FromSeconds(5));
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,(ThreadStart)delegate()
{
lblHello.Content = "Hello,Dispatcher";
});
}


如果在其他工程或者类中,我们可以用 Application.Current.Dispatcher.Invoke方法来完成同样的操作,它们都指向 UI Thread Dispatcher这个唯一的对象。

Dispatcher 同时还支持 BeginInvoke 异步调用,如下代码:

private void btnHello_Click(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new Action(() =>
{
Thread.Sleep(TimeSpan.FromSeconds(5));
this.lblHello.Content = DateTime.Now.ToString();
}));
}).Start();
}

关于Dispatcher和WPF多线程,还有很多要讲,由于篇幅有限且精力有限,我这里只讲一些我们最常见的应用,同时包括Freezable 的处理等问题,大家可以查阅MSDN或者查阅国外相关的专题。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多