【WPF.NET开发】弱事件模式
本文内容
- 先决条件
- 为什么要实现弱事件模式?
- 应该由谁实现弱事件模式?
- 如何实现弱事件模式
在应用程序中,附加到事件源的处理程序可能不会与将处理程序附加到源的侦听器对象一同销毁。 这种情况下会导致内存泄漏。 Windows Presentation Foundation (WPF) 引入了可用于解决此问题的设计模式。 设计模式为特定事件提供专用的管理器类,并在该事件的侦听器上实现接口。 此设计模式称为弱事件模式。
1、先决条件
本文假定你对路由事件有基本的了解,并且已阅读
路由事件概述。 若要遵循本文中的示例,如果熟悉 Extensible Application Markup Language (XAML) 并知道如何编写 Windows Presentation Foundation (WPF) 应用程序,将会很有帮助。
2、为什么要实现弱事件模式?
对事件的侦听可能会导致内存泄漏。 侦听事件的常用技术是使用特定于语言的语法,将处理程序附加到源上的事件。 例如,C# 语句 source.SomeEvent += new SomeEventHandler(MyEventHandler) 或 VB 语句 AddHandler source.SomeEvent, AddressOf MyEventHandler。 然而,此技术可创建从事件源到事件侦听器的强引用。 除非显式注销事件处理程序,否则侦听器的对象生存期将受到源的对象生存期的影响。 在某些情况下,你可能希望通过其他因素(例如,当前是否属于应用程序的可视化树)控制侦听器的对象生存期。 每当源的对象生存期超出侦听器的有用对象生存期时,侦听器的存活时间比必要时间要长。 在这种情况下,未分配的内存相当于内存泄漏。
弱事件模式旨在解决内存泄漏问题。 当侦听器需要注册事件时,都可以使用弱事件模式,但侦听器并不明确知晓事件会在何时注销。 当源的对象生存期超过侦听器的有用对象生存期时,也可以使用弱事件模式。 在这种情况下,有用与否将由你来决定。 弱事件模式允许侦听器注册事件和接收事件,而不会以任何方式影响侦听器的对象生存期特征。 实际上,对源的隐式引用并不能确定侦听器是否有资格执行垃圾回收。 由于是弱引用,因而引用是对弱事件模式和相关 API 的命名。 侦听器可以被垃圾回收或以其他方式销毁,而源可以继续运行,无需保留针对现已销毁的对象的不可回收的处理程序引用。
3、应该由谁实现弱事件模式?
弱事件模式主要与控件作者相关。 控件作者主要负责控件行为和控件包含,以及控件对其所插入的应用程序的影响。 这包括控件对象生存期行为,特别是处理所述的内存泄漏问题。
某些方案本身就适合应用弱事件模式。 此类方案之一是数据绑定。 在数据绑定中,源对象通常独立于作为绑定目标的侦听器对象。 WPF 数据绑定的许多方面已经在事件的实现方式上应用了弱事件模式。
4、如何实现弱事件模式
有四种方法可以实现弱事件模式,每种方法都使用不同的事件管理器。 选择最适合你的方案的事件管理器。
-
现有弱事件管理器
:当要订阅的事件具有对应的 WeakEventManager,请使用现有的弱事件管理器。 有关 WPF 附带的弱事件管理器列表,请参阅
WeakEventManager类中的继承层次结构。 由于包含的弱事件管理器有限,可能需要选择其他方法中的一个。 -
通用弱事件管理器:如果现有的 WeakEventManager<TEventSource,TEventArgs> 事件不可用,并且你正在寻找实现弱事件的最简单方法,请使用泛型 WeakEventManager。 但是,泛型
WeakEventManager<TEventSource,TEventArgs>比现有或自定义弱事件管理器更低效,因为它使用反射从其名称中发现事件。 此外,使用泛型WeakEventManager<TEventSource,TEventArgs>注册事件所需的代码比使用现有或自定义WeakEventManager注册事件所需的代码更详细。 -
自定义弱事件管理器:在现有 WeakEventManager 不可用且效率至关重要时,创建自定义的
WeakEventManager。 尽管比泛型WeakEventManager更有效,但自定义WeakEventManager要求编写更多前期代码。 -
第三方弱事件管理器:
-
当需要其他方法未提供的功能时,请使用第三方弱事件管理器。 NuGet 具有一些较弱的事件管理器
。
以下部分介绍如何通过使用不同的事件管理器类型来实现弱事件模式。 对于泛型和自定义弱事件管理器示例,要订阅的事件具有以下特征。
- 事件名称为
SomeEvent。 - 事件由
SomeEventSource类引发。 - 事件处理程序的类型为
EventHandler<SomeEventArgs>。 - 事件将
SomeEventArgs类型的参数传递给事件处理程序。
4.1 使用现有弱事件管理器类
-
查找现有弱事件管理器。 有关 WPF 附带的弱事件管理器列表,请参阅 WeakEventManager 类的继承层次结构。
-
使用新的弱事件管理器,而不是普通事件挂钩。
例如,如果代码使用以下模式订阅事件:
source.LostFocus += new RoutedEventHandler(Source_LostFocus);将其更改为以下模式:
LostFocusEventManager.AddHandler(source, Source_LostFocus);同样,如果代码使用以下模式取消订阅事件:
source.LostFocus -= new RoutedEventHandler(Source_LostFocus);将其更改为以下模式:
LostFocusEventManager.RemoveHandler(source, Source_LostFocus);
4.2 使用泛型弱事件管理器类
使用泛型 WeakEventManager<TEventSource,TEventArgs> 类,而不是普通事件挂钩。
使用 WeakEventManager<TEventSource,TEventArgs> 注册事件侦听器时,需要将事件源和 EventArgs 类型作为类型参数提供给类。 调用 AddHandler,如以下代码所示:
WeakEventManager<SomeEventSource, SomeEventArgs>.AddHandler(source, "SomeEvent", Source_SomeEvent);
4.3 创建自定义弱事件管理器类
-
将以下类模板复制到项目。 以下类继承自 WeakEventManager 类:
class SomeEventWeakEventManager : WeakEventManager {private SomeEventWeakEventManager(){}/// <summary>/// Add a handler for the given source's event./// </summary>public static void AddHandler(SomeEventSource source,EventHandler<SomeEventArgs> handler){if (source == null)throw new ArgumentNullException(nameof(source));if (handler == null)throw new ArgumentNullException(nameof(handler));CurrentManager.ProtectedAddHandler(source, handler);}/// <summary>/// Remove a handler for the given source's event./// </summary>public static void RemoveHandler(SomeEventSource source,EventHandler<SomeEventArgs> handler){if (source == null)throw new ArgumentNullException(nameof(source));if (handler == null)throw new ArgumentNullException(nameof(handler));CurrentManager.ProtectedRemoveHandler(source, handler);}/// <summary>/// Get the event manager for the current thread./// </summary>private static SomeEventWeakEventManager CurrentManager{get{Type managerType = typeof(SomeEventWeakEventManager);SomeEventWeakEventManager manager =(SomeEventWeakEventManager)GetCurrentManager(managerType);// at first use, create and register a new managerif (manager == null){manager = new SomeEventWeakEventManager();SetCurrentManager(managerType, manager);}return manager;}}/// <summary>/// Return a new list to hold listeners to the event./// </summary>protected override ListenerList NewListenerList(){return new ListenerList<SomeEventArgs>();}/// <summary>/// Listen to the given source for the event./// </summary>protected override void StartListening(object source){SomeEventSource typedSource = (SomeEventSource)source;typedSource.SomeEvent += new EventHandler<SomeEventArgs>(OnSomeEvent);}/// <summary>/// Stop listening to the given source for the event./// </summary>protected override void StopListening(object source){SomeEventSource typedSource = (SomeEventSource)source;typedSource.SomeEvent -= new EventHandler<SomeEventArgs>(OnSomeEvent);}/// <summary>/// Event handler for the SomeEvent event./// </summary>void OnSomeEvent(object sender, SomeEventArgs e){DeliverEvent(sender, e);} } -
重命名
SomeEventWeakEventManager、SomeEvent、SomeEventSource和SomeEventArgs以匹配事件名称。 -
设置弱事件管理器类的
访问修饰符,用于匹配其管理的事件的可访问性。 -
使用新的弱事件管理器,而不是普通事件挂钩。
例如,如果代码使用以下模式订阅事件:
source.SomeEvent += new EventHandler<SomeEventArgs>(Source_SomeEvent);将其更改为以下模式:
SomeEventWeakEventManager.AddHandler(source, Source_SomeEvent);同样,如果代码使用以下模式取消订阅事件:
source.SomeEvent -= new EventHandler<SomeEventArgs>(Source_SomeEvent);将其更改为以下模式:
SomeEventWeakEventManager.RemoveHandler(source, Source_SomeEvent);
相关文章:
【WPF.NET开发】弱事件模式
本文内容 先决条件为什么要实现弱事件模式?应该由谁实现弱事件模式?如何实现弱事件模式 在应用程序中,附加到事件源的处理程序可能不会与将处理程序附加到源的侦听器对象一同销毁。 这种情况下会导致内存泄漏。 Windows Presentation Found…...
[Angular] 笔记 16:模板驱动表单 - 选择框与选项
油管视频: Select & Option (Template Driven Forms) Select & Option 在 pokemon.ts 中新增 interface: export interface Pokemon {id: number;name: string;type: string;isCool: boolean;isStylish: boolean;acceptTerms: boolean; }// new interface…...
Webpack基础使用
目录 一.什么是Webpack 二.为什么要使用Webpack 三.Webpack的使用 1.下载yarn包管理器 2.Webpack的安装 3.Webpack的简单使用 4.效果 四.Webpack打包流程 一.什么是Webpack Webpack是一个静态模块打包工具 二.为什么要使用Webpack 在开发中,我们常常会遇到…...
扭蛋机小程序搭建:打造互联网“流量池”
随着互联网科技的发展,扭蛋机小程序成为了市场发展的重要力量。 扭蛋机市从日本发展流行起来的,玩法就是根据设置的概率,让玩家体验扭蛋机的乐趣。扭蛋机中有隐藏款和稀有款,为了获得稀有款商品,玩家便会进行扭蛋&…...
解决VNC连接Ubuntu服务器打开终端出现闪退情况
服务器环境 阿里云ECS服务器 操作系统:Ubuntu 20.0.4 如何使用VNC连接阿里云ECS服务器 1.阿里云官方指导:通过VNC搭建Ubuntu 18.04和20.04图形界面 2.新手入门ECS——ubuntu 20.04安装图形化界面和本地VNC连接 问题描述 使用VNC连接上新申请阿里云服…...
flutter是什么
“flutter” 是一种移动应用开发框架,由谷歌开发和维护。Flutter 可用于构建高性能、美观且跨平台的移动应用程序,它支持同时在多个平台上运行,包括: iOS:可以构建原生的iOS应用。 Android:可以构建原生的…...
GET和POST请求
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、GET请求二、POST请求三.幂等性是什么总结 前言 GET和POST是HTTP协议中的两种常见的请求方法,它们定义了客户端与服务器之间进行通信时的不同方…...
基于电商场景的高并发RocketMQ实战-Broker写入读取流程性能优化总结、Broker基于Pull模式的主从复制原理
🌈🌈🌈🌈🌈🌈🌈🌈 【11来了】文章导读地址:点击查看文章导读! 🍁🍁🍁🍁🍁🍁dz…...
前端DApp开发利器,Ant Design Web3 正式发布 1.0
在介绍 Ant Design Web3 之前,先简单说说 Web3 DApp(去中心化应用)。DApp 可以说是除了 AI 应用外当下最受前端独立开发者青睐的应用了。当然,在 ChatGPT 还没有火的时候,Web3 DApp 才是最火的。因为通过一个连接区块链的 DApp(去中心化应用)你可以获得如下能力: 💰交…...
[RoarCTF 2019]Easy Java(java web)
题目 页面如下 页面长得像sql注入 点击help看一下 这里需要了解java web目录结构 WEB INF:Java的web应用安全目录; 此外如果想在页面访问WEB-INF应用里面的文件,必须要通过web.xml进行相应的映射才能访问; WEB-INF是Java Web应用程序中的一…...
Abaqus许可管理策略
随着全球化和数字化的发展,知识产权和许可管理成为了企业成功的关键因素之一。在这样的背景下,Abaqus许可管理策略应运而生,为企业提供了一个全面、灵活和可扩展的解决方案,帮助企业掌控业务许可,实现增长与合规。 Ab…...
对采集到的温湿度数据,使用python进行数据清洗,并使用预测模型进行预测未来一段时间的温湿度数据。
使用Python对传感器采集到的数据进行数据清洗和预测未来一段时间的温湿度数据,您可以按照以下步骤进行操作: 导入必要的库 import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.linear_model …...
嵌入式SOC之通用图像处理之OSD文字信息叠加的相关实践记录
机缘巧合 机缘巧合下, 在爱芯元智的xx开发板下进行sdk的开发.由于开发板目前我拿到是当前最新的一版(估计是样品),暂不公开开发板具体型号信息.以下简称板子 .很多优秀的芯片厂商,都会提供与开发板配套的完善的软件以及完善的技术支持(FAE),突然觉得爱芯…...
Java日期工具类LocalDateTime
Java日期工具类LocalDateTime 嘚吧嘚LocalDateTime - API创建时间获取年月日时分秒增加时间减少时间替换时间日期比较 嘚吧嘚 压轴的来了,个人感觉LocalDateTime是使用频率最高的工具类,所以本篇像文章详细研究说明一下🧐。 如果看了Java日期…...
从C到C++1
一.思想过渡 前言:明确地说,学了C语言就相当于学了 C 的一半,从C语言转向 C 时,不需要再从头开始,接着C语言往下学就可以,所以我强烈建议先学C语言再学 C。 1.面向过程与面向对象 从“学院派”的角度来…...
[Angular] 笔记 18:Angular Router
Angular Router 视频 chatgpt: Angular 具有内置的大量工具、功能和库,功能强大且经过良好设计,如组件化架构、依赖注入、模块化系统、路由和HTTP客户端等。这些功能可以直接用于项目中,无需额外的设置或第三方库。这简化了开发流…...
微服务全链路灰度方案介绍
目录 一、单体架构下的服务发布 1.1 蓝绿发布 二、微服务架构下的服务发布 三、微服务场景下服务发布的问题 四、全链路灰度解决方案 4.1 物理环境隔离 4.2 逻辑环境隔离 4.3 全链路灰度方案实现技术 4.3.1 标签路由 4.3.2 节点打标 4.3.3 流量染色 4.3.4 分布式链路…...
低代码开发OA系统 低代码平台如何搭建OA办公系统
随着企业业务的复杂化和信息化的推进,如何快速、高效地构建一个适应企业发展需求的OA系统成为许多企业关注的焦点。本文将介绍低代码开发在构建OA系统方面的优势,并以白码低代码平台为例,探讨其在实际应用中的价值和功能。 什么是低代码开发?…...
构建Python的Windows整合包教程
构建Python的Windows整合包教程 原文链接:https://blog.gcc.ac.cn/post/2023/buildpythonwindowsintegrationpackagetutorial/ 构建Python的Windows整合包教程 - 我的博客原文链接 前言 之前的开源项目本地素材搜索有很多人想要Windows整合包,因为Wi…...
《整机柜服务器通用规范》由OCTC正式发布!浪潮信息牵头编制
近日,中国电子工业标准化技术协会开放计算标准工作委员会(OCTC)正式批准发布了《整机柜服务器通用规范》,该标准由浪潮信息牵头,中国工商银行、中国质量认证中心、英特尔、中国计量科学研究院等十余家单位联合编制&…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
