.NET_Dispatcher与DispatcherObject

24 篇文章 20 订阅


一、Dispatcher

译为调度程序/调度器。

1.1 定义

提供用于管理线程工作项队列的服务。
所以它是一个抽象的东西,用于管理线程工作项的。

1.2 示例

下面示例演示了如何在Dispatcher中放置一个操作。
首先,创建一个无参的delegate(委托)。

public delegate void NextPrimeDelegate();

接下来,调用BeginInvoke(DispatcherPriority, Delegate)。该调用传入两个参数:

  • DispatcherPriority,调用优先级,设置为DispatcherPriority.Normal
  • 回调函数,通过委托NextPrimeDelegate的一个实例传入
startStopButton.Dispatcher.BeginInvoke(
    DispatcherPriority.Normal,
    new NextPrimeDelegate(CheckNextNumber));

1.3 附注

Dispatcher为特定线程维护一个优先级队列,队列中里面含有工作项,

在线程上创建了一个Dispatcher后,即使Dispatcher已关闭,该线程也只能与该Dispatcher关联。

若你尝试为当前线程获取CurrentDispatcher,但当前线程没有关联的Dispatcher,则会创建一个Dispatcher。 当你创建一个DispatcherObject时,也会创建一个Dispatcher。 若你在后台线程创建了一个Dispatcher,请确保在退出线程之前关闭该Dispatcher。

若一个Dispatcher被关闭了,则不能被重启。

在WPF中,只有与之关联的Dispatcher才能访问DispatcherObject(这是为了保护程序,增加程序安全性;否则新手乱跨线程访问UI资源,程序动不动就会崩溃)。例如,后台线程无法更新与UI线程上的Dispatcher关联的Button的内容。 为了使后台线程可以访问Button的Content属性,必须将作业委托给UI线程关联的Dispatcher。 可以使用Invoke或BeginInvoke来完成此操作。Invoke是同步的,而BeginInvoke是异步的。操作会添加到指定DispatcherPriority的Dispatcher队列中。

如果在一个已经关闭的Dispatcher上调用BeginInvoke,返回DispatcherOperation的status属性被设置为Aborted。

除了DisableProcessing,Dispatcher上的所有方法都是自由线程的(free-threaded)

从DispatcherObject派生的对象具有线程亲缘性/亲和性(thread affinity)

从Freezable派生的对象在冻结时是自由线程的。

自由线程

就是多个线程可以自由访问。不过这不意味着多线程访问是安全的,可能需要自己加锁来实现访问安全性。

线程亲缘性
指某些资源或对象与特定线程的关联性。这意味着这些资源或对象只能由与之关联的线程进行访问和操作。在多线程编程中,线程亲和性是一种保护机制,可以防止来自其他线程的未经授权的访问和冲突。


二、DispatcherObject

2.1 定义

表示一个与Dispatcher关联的对象。

2.2 附注

只有创建Dispatcher的线程才能直接访问DispatcherObject。要从其他线程访问DispatcherObject,得在与DispatcherObject关联的Dispatcher上调用Invoke或BeginInvoke。

需要强制线程安全的DispatcherObject子类可以在所有公有方法上调用VerifyAccess。这样可以确保调用线程是创建DispatcherObject的线程。

DispatcherObject不能单独实例化;也就是说,所有构造函数都是protected。

从DispatcherObject派生的对象具有线程亲缘性。

从Freezable派生的对象在冻结时是自由线程的。

2.3 线程安全性

该类的所有公有的静态成员都是线程安全的。任何实例成员都不保证线程安全。

此对象只能从创建它的线程访问。尝试从其他线程访问时将抛出InvalidOperationException。Invoke(DispatcherPriority, Delegate) 或BeginInvoke(DispatcherPriority, Delegate) 为将工作引导至正确的线程提供支持。

⭐2.4 哪些东西是DispatcherObject

讲了这么久的DispatcherObject,那到底实际编程中哪些东西是DispatcherObject?
我截了个Button类的继承关系图:
在这里插入图片描述
可以看到,Object派生了DispatcherObject,而DispatcherObject与我们平时接触的控件(Control)之间还隔了那么多层关系。这表示DispatcherObject的层次相当高,很多类都派生自它。

具体地,如各种常见控件、窗体等。


三、Dispatcher与DispatcherObject

根据上面两节描述,我画了一张Dispatcher与DispatcherObject的关系图。
在这里插入图片描述
学过计算机的都知道,线程是调度单元,它是用来执行代码的。
dispatcher作为调度程序,会把队列中排好的作业项(从第一节来看,应该是委托?)喂给线程执行。
该线程中创建的dispatcherObject将与dispatcher产生关联。

3.1 WPF中的应用场景

第一节中提到,在WPF中,只有与线程关联的Dispatcher才能访问DispatcherObject。
新手可能会这样使用:后台开个线程,去修改UI窗口中控件的内容,于是运行遇到不支持跨线程访问的报错。解决方案也很简单,用this.Dispatcher.Invoke/BeginInvoke即可;但是呢,这本质上还是单线程的。建议把耗时的数据处理放到后台线程中执行,待数据处理完毕,再在UI线程中对数据进行显示。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值