dotnet 读 WPF 源代码笔记 AppDomainShutdownMonitor 的设计
本文是我在读 WPF 源代码做的笔记。在 WPF 中的 AppDomainShutdownMonitor 类是一个不开放的类,这个类当前只是给 D3DImage 类使用。在 AppDomainShutdownMonitor 提供了在应用的进程或程序域关闭的时候,进行一次通知,当前是用来清理 D3DImage 类的资源
在 WPF 中的 D3DImage 类是一个充满黑科技的类,这个类因为黑科技而有这样的要求,在进程退出或程序域关闭的时候,需要调用特别的逻辑进行释放资源。同时在 D3DImage 类被回收的时候,就不需要订阅进程退出或程序域关闭的时候的清理逻辑,因为在 D3DImage 回收的时候,将会自动执行清理逻辑
如果让 D3DImage 类去关注进程退出等,那么将会让 D3DImage 类更加复杂,因此在 WPF 里面加入了一个叫 IAppDomainShutdownListener 的接口,定义如下
internal interface IAppDomainShutdownListener{void NotifyShutdown();}
这是一个不开放的接口,继承这个接口的类可以获得在 AppDomain 退出的时候的通知
为了实现这个接口的调用功能,在 WPF 中定义了静态类 AppDomainShutdownMonitor 类,这个类里面将会提供注入 IAppDomainShutdownListener 对象,在 AppDomain 退出的时候调用 IAppDomainShutdownListener 对象的 NotifyShutdown 方法,大概逻辑如下
static AppDomainShutdownMonitor(){AppDomain.CurrentDomain.DomainUnload += OnShutdown;AppDomain.CurrentDomain.ProcessExit += OnShutdown;}public static void Add(IAppDomainShutdownListener listener){// 忽略代码}private static void OnShutdown(object sender, EventArgs e){// 忽略代码listener.NotifyShutdown();}
如果只是这样的实现将会存在问题,因为 AppDomainShutdownMonitor 是静态类,如果在 Add 方法传入的是对象,被 AppDomainShutdownMonitor 的静态字段保存了,那么将无法释放 IAppDomainShutdownListener 对象。因此在 WPF 中的实际实现是采用一个 WeakReference 来实现
在当时的 WPF 开发的时候,还没有 WeakReference<>
类型
更改之后的逻辑大概如下
public static void Add(WeakReference listener){Debug.Assert(listener.Target != null);Debug.Assert(listener.Target is IAppDomainShutdownListener);lock (_dictionary){if (!_shuttingDown){_dictionary.Add(listener, listener);}}}private static Dictionary<WeakReference, WeakReference> _dictionary;
为什么上面的存放 listener 对象的容器是 Dictionary 而不是 List 呢?因为还有这样的需求,在 D3DImage 类被回收的时候,就不需要订阅进程退出或程序域关闭的时候的清理逻辑,因此还有一个 Remove 方法
public static void Remove(WeakReference listener){Debug.Assert(listener.Target == null || listener.Target is IAppDomainShutdownListener);lock (_dictionary){if (!_shuttingDown){_dictionary.Remove(listener);}}}
调用 Add 和 Remove 的代码分别如下
public D3DImage(double dpiX, double dpiY){// 忽略代码_listener = new WeakReference(this);AppDomainShutdownMonitor.Add(_listener);}~D3DImage(){// 忽略代码AppDomainShutdownMonitor.Remove(_listener);}
为了能更快的调用 Remove 方法,也就将存放的容器设计为 Dictionary 了,但实际上没有使用链表快,想不开的话,我会去优化一下这个逻辑
通过上面的逻辑,相信大家也了解到如何写出在应用退出的时候的逻辑,以及编写的时候可以参阅 WPF 的设计,尽管因为 WPF 写这段逻辑的时候很多好用的特性还没开发出来,但是需要稍微做一点改动,就可以用上新特性加上这个设计方式做到在应用退出的时候执行一些逻辑的清理
当前的 WPF 在 https://github.com/dotnet/wpf 完全开源,使用友好的 MIT 协议,意味着允许任何人任何组织和企业任意处置,包括使用,复制,修改,合并,发表,分发,再授权,或者销售。在仓库里面包含了完全的构建逻辑,只需要本地的网络足够好(因为需要下载一堆构建工具),即可进行本地构建
我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新
如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入
如有不方便在博客评论的问题,可以加我 QQ 2844808902 交流
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
dotnet 读 WPF 源代码笔记 AppDomainShutdownMonitor 的设计相关推荐
- dotnet 读 WPF 源代码笔记 WriteableBitmap 的渲染和更新是如何实现
在 WPF 框架提供方便进行像素读写的 WriteableBitmap 类,本文来告诉大家在咱写下像素到 WriteableBitmap 渲染,底层的逻辑 之前我使用 WriteableBitmap ...
- dotnet 读 WPF 源代码笔记 提升调试效率的 NamedObject 类型
本文来聊聊 WPF 那些值得称赞的设计中的 NamedObject 类型.在 WPF 中,有很多值得我学习的设计开发思想,其中就包括本文将要介绍的 NamedObject 类型.此类型的定义仅仅只是为 ...
- dotnet 读 WPF 源代码笔记 创建 SolidColorBrush 性能没有想象那么差
在 WPF 中,常用的画刷里面有纯色画刷 SolidColorBrush 类.因为画刷会对应到 DirectX 的资源,因此之前我以为纯色画刷其实会比 Color 会占用更多的资源.在 WPF 中 C ...
- dotnet 读 WPF 源代码笔记 了解 WPF 已知问题 用户设备上不存在 Arial 字体将导致应用闪退...
本文来告诉大家 WPF 已知问题,在用户的设备上,如果不存在 Arial 字体,同时安装了一些诡异的字体,那么也许就会让应用在使用到诡异的字体的时候,软件闪退 在 WPF 的 FontFamily.c ...
- dotnet 读 WPF 源代码笔记 渲染收集是如何触发
在 WPF 里面,渲染可以从架构上划分为两层.上层是 WPF 框架的 OnRender 之类的函数,作用是收集应用程序渲染的命令.上层将收集到的应用程序绘制渲染的命令传给下层,下层是 WPF 的 GF ...
- dotnet 读 WPF 源代码笔记 插入触摸设备的初始化获取设备信息
在 WPF 触摸应用中,插入触摸设备,即可在应用里面使用上插入的触摸设备.在 WPF 使用触摸设备的触摸时,需要获取到触摸设备的信息,才能实现触摸 获取触摸设备插入 在 WPF 中,通过 Window ...
- 《深入浅出WPF》笔记——绑定篇(一)
上一节,有记录写到:在WPF里,数据驱动UI,数据占核心地位,UI次之.怎么恢复数据的核心地位,那就要先了解一下Binding. 一.Binding 基础 1.1WPF中Data Binding的带来 ...
- 《深入浅出WPF》笔记——模板篇
原文:<深入浅出WPF>笔记--模板篇 我们通常说的模板是用来参照的,同样在WPF中,模板是用来作为制作控件的参照. 一.认识模板 1.1WPF菜鸟看模板 前面的记录有提过,控件主要是算法 ...
- WPF学习笔记:XAML入门
1.什么是XAML XAML是WPF技术中专门用于设计UI的语言,它在桌面开发及富媒体网络程序的开发中扮演了HTML+CSS+JAVASCRIPT的角色,成为设计师和程序员之间沟通的桥梁.它帮助开发团 ...
最新文章
- 冬季生存法则,不得不看!
- 上市3年市值缩水9成,AI教育第一股流利说谋求私有化
- Memcached存储机制
- 路由器中虚拟服务器设置,路由器中虚拟服务器设置方法
- Windows内核对象管理
- 实现java的outline功能_在单独的功能文件中重用Scenario Outline中的示例
- mysql 加号的作用_MySQL学习笔记(一)
- 【机器学习】决策树知识点小结
- 生成一个GitHub的token用于git推送本地库至远程库
- Arm学习总结之 32位和64位寄存器
- python mpi 多节点_python – 如何找到MPI(4PY)可用的内核数量?
- Qt resizeEvent 控件居中设置
- DOS批处理不支持将UNC 路径作为当前目录的巧妙解决方案
- Java入门系列-24-实现网络通信
- AVD Manager
- [Swift]LeetCode831. 隐藏个人信息 | Masking Personal Information
- 网线的分类及速率,您知道吗?
- 马云请不动郭盛华的原因?原来背后还有更神秘的人物
- H3C无线网络延时大、数据丢包,不能上网,原来是有BUG
- VS2008 简体中文正式版序列号(到期解决办法)