WPF 中那些可跨线程访问的 DispatcherObject(WPF Free Threaded Dispatcher Object)

阅读: 评论:0

WPF 中那些可跨线程访问的 DispatcherObject(WPF Free Threaded Dispatcher Object)

WPF 中那些可跨线程访问的 DispatcherObject(WPF Free Threaded Dispatcher Object)

众所周知的,WPF 中多数对象都继承自 DispatcherObject,而 DispatcherObject 带给这些对象一个特点:不能跨线程访问。

不过,WPF 中依然存在一些例外。本文将介绍 WPF 那些可跨线程访问的 DispatcherObject,如何充分利用这个特点提高应用程序的性能,以及如何自己编写这样的 DispatcherObject


本文内容

    • 什么样的 DispatcherObject 可以跨线程访问?
      • Dispatcher 属性
      • CheckAccess 和 VerifyAccess
      • _dispatcher 的重新赋值
      • _dispatcher 赋值为 null
    • 哪些 DispatcherObject 是可以跨线程访问的?
      • Freezable
      • Style
      • Template
      • Style 和 Template
    • 强制让一个 DispatcherObject 跨线程访问
    • 总结

什么样的 DispatcherObject 可以跨线程访问?

要了解什么样的 DispatcherObject 可以跨线程访问,需要知道 WPF 是如何限制对象的跨线程访问的。

Dispatcher 属性

DispatcherObject 类有一个 Dispatcher 属性,它长下面这样:

public Dispatcher Dispatcher
{get{// This property urn _dispatcher;}
}

属性在 Dispatcher 的构造函数中被赋值:

protected DispatcherObject()
{_dispatcher = Dispatcher.CurrentDispatcher;
}

CheckAccess 和 VerifyAccess

DispatcherObject 提供了两种验证 Dispatcher 的方法,CheckAccessVerifyAccess;他们内部的实现是调用 Dispatcher 类型的 CheckAccessVerifyAccess 方法。

CheckAccess 用于检查调用线程对此对象是否有访问权,如果有访问权,则返回 true,否则返回 false。而 VerifyAccess 也是用于检查调用线程对此对象是否有访问权,如果没有访问权会抛出异常。

你可以阅读这两个方法的代码来了解其实现原理。每个方法只有短短的一两行而已,非常容易理解。

/// <summary>
///     Checks that the calling thread has access to this object.
/// </summary>
/// <remarks>
///     Only the dispatcher thread may access DispatcherObjects.
///     <p/>
///     This method is public so that any thread can probe to
///     see if it has access to the DispatcherObject.
/// </remarks>
/// <returns>
///     True if the calling thread has access to this object.
/// </returns>
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public bool CheckAccess()
{return Thread == Thread.CurrentThread;
}/// <summary>
///     Verifies that the calling thread has access to this object.
/// </summary>
/// <remarks>
///     Only the dispatcher thread may access DispatcherObjects.
///     <p/>
///     This method is public so that derived classes can probe to
///     see if the calling thread has access to itself.
/// </remarks>
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void VerifyAccess()
{if(!CheckAccess()){throw new InvalidOperationException(SR.Get(SRID.VerifyAccess));}
}

需要说明的是,只有调用这两个方法才会对线程的访问权限进行检查。如果你写一个类继承自 DispatcherObject 而在你的属性和方法中不直接或间接调用 VerifyAccess,那么这是不受线程访问限制的。

只不过,WPF 封装的大多对象和属性都调用了 VerifyAccess(例如依赖项属性),所以很大程度上限制了 WPF UI 的线程访问权限。

_dispatcher 的重新赋值

Dispatcher 属性的获取实际上就是在拿 _dispatcher 字段的值。于是我们现在仔细寻找 _dispatcher 的所有赋值代码,只有三处,就是下面这三个方法:

  1. 构造函数,会赋值为当前线程的 Dispatcher
  2. DetachFromDispatcher,会赋值为 null
  3. MakeSentinel,会赋值为另一个线程的 Dispatcher 的值(即一个线程创建,但由另一个线程来使用)。
/// <summary>
///     Instantiate this object associated with the current Dispatcher.
/// </summary>
protected DispatcherObject()
{_dispatcher = Dispatcher.CurrentDispatcher;
}// This method allows certain derived classes to break the dispatcher affinity
// of our objects.
[FriendAccessAllowed] // Built into Base, also used by Framework.
internal void DetachFromDispatcher()
{_dispatcher = null;
}// Make this object a "sentinel" - it can be used in equality tests, but should

本文发布于:2024-02-02 02:54:03,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170681565240932.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:线程   DispatcherObject   WPF   Free   Object
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23