C# 闭包类对弱引用的坑
闭包、弱引用的简单概念,大佬们描述的很多,有不了解的可以看看:
组里小伙伴报了个BUG,定义的封装事件DeviceDown不生效了
瞅了下,貌似没啥问题,单元测试、Demo都是okay的
虽然基本确认是业务层代码调用方面的问题,但还是要继续查根本原因
然后发现,弱引用WeakRefrence中的Target为Null了。

了解WeakRefrence的都知道,Null值代表对象被回收掉了。
剥离部分代码后,发现只剩下一个类SelectionBoxSingleEventor、一个相关初始化方法,我简化了下:
1 /// <summary>
2 /// 初始化选择框区域事件传递
3 /// </summary>
4 /// <param name="element"></param>
5 /// <param name="selectionBoxOperations"></param>
6 /// <returns></returns>
7 private DeviceEventTransformer InitAreaTransformer(FrameworkElement element, SelectionBoxOperations selectionBoxOperations)
8 {
9 var transformer = new DeviceEventTransformer(element);
10 transformer.DeviceDown += (sender, e) =>
11 {
12 if (e.DeviceType != DeviceType.Mouse) return;
13
14 CaptureDevice(e);
15 DeviceDown?.Invoke(sender, new BoxDeviceInputArgs(e) { OperationMode = selectionBoxOperations});
16 };
17 return transformer;
18 }
看起来没啥问题,这里有个闭包函数。
继续定位,发现弱引用创建时对象的数据,有.<>_DisplayClass字样:

原来是闭包搞的鬼。闭包函数这里编译器会自动生成一个临时变量类(也可以把它叫做闭包类吧),用于对执行一段函数,常见于Lamda、委托操作。
这个闭包类,因为没有其它代码对其强引用,所以一段时间后程序会自动回收。
闭包类回收后,我的代码就出问题了,因为按照开发人员的期望,他的委托是要一直执行的。
我加了个兼容处理,具体见下方代码
1 /// <summary>
2 /// 对象是否支持弱引用
3 /// </summary>
4 /// <param name="target"></param>
5 /// <returns></returns>
6 private bool CanSupportWeakReference(object target)
7 {
8 //target为空,一般是静态类,委托无法传入对象值
9 if (target == null)
10 {
11 return false;
12 }
13 //临时变量类(又称闭包类),没有其它位置引用它,如果对此对象弱引用,会因对象自动回收导致事件无法接收到。
14 //所以,我们不建议使用变量传递到委托里执行,此处我们兼容了但依然会存在内存泄漏问题。
15 if (target.ToString().Contains(".<>c"))
16 {
17 return false;
18 }
19 return true;
20 }
因为目前来看,闭包类名称一般有“.<>c_DisplayClass”的关键字。而当委托中没有执行代码,即空函数时,关键字只有“.<>c”。
通过上面对类名称的分析,判断对象是否支持弱引用。不支持弱引用,直接使用事件即可(弱引用都不支持了,管他内存泄不泄漏。。。)
C# 闭包类对弱引用的坑的更多相关文章
- Java中弱引用、软引用、虚引用及强引用的区别
Java中弱引用VS软引用 Java中有如下四种类型的引用: 强引用(Strong Reference) 弱引用(WeakReference) 软引用(SoftReference) 虚引用(Phant ...
- weakref:对象的弱引用
介绍 weakref支持对象的弱引用,正常的引用会增加对象的引用计数,并避免它被垃圾回收.但结果并不是总和期望的那样,比如有时候可能会出现一个循环引用,或者有时候需要内存时可能要删除对象的缓存.而弱引 ...
- 初解C#类、结构、弱引用
一.类 类中的数据和函数称为类的成员 数据成员是包含类的数据----字段.常量和事件的成员.数据成员可以是静态数据.类成员总是实例成员,除非用static进行显示的声明. 事件是类的成员,在发生某些行 ...
- android WeakReference(弱引用 防止内存泄漏)与SoftReference(软引用 实现缓存机制(cache))
在Android开发中,基本上很少有用到软引用或弱引用,这两个东东若用的很好,对自己开发的代码质量的提高有很大的帮助.若用的不好,会坑了自己.所以,在还没有真正的去了解它们之前,还是慎用比较好. 下面 ...
- 弱引用?强引用?未持有?额滴神啊-- Swift 引用计数指导
ARC ARC 苹果版本的自动内存管理的编译时间特性.它代表了自动引用计数(Automatic Reference Counting).也就是对于一个对象来说,只有在引用计数为0的情况下内存才会被释放 ...
- IOS 看懂此文,你的block再也不需要WeakSelf弱引用了!
前言: 最近都在折腾 Sagit 架框的内存释放的问题,所以对这一块有些心得. 对于新手,学到的文章都在教你用:typeof(self) __weak weakSelf = self. 对于老手,可能 ...
- Python引用复制,参数传递,弱引用与垃圾回收
引用 先上个示例: >>> val = [1] >>> val[0] = val >>> val [[...]] 上述代码使val中包含自身,而产 ...
- c++弱引用与强引用
https://www.zhihu.com/question/26851369 智能指针一个很重要的概念是"所有权",所有权意味着当这个智能指针被销毁的时候,它指向的内存(或其它资 ...
- Android 弱引用和软引用
软引用 和 弱引用 1. SoftReference<T>:软引用-->当虚拟机内存不足时,将会回收它指向的对象:需要获取对象时,可以调用get方法. 2. WeakRefere ...
随机推荐
- JavaScript数组常用的方法总结
数组常用方法 concat() 方法 concat() 方法用于连接两个或多个数组. 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本. var arr = new Array(3) arr ...
- pytest之运行环境
简介 pytest是Python最流程化的单元测试框架,它具有允许直接使用assert进行断言,而不需要使用self.assert*:可以自动寻找单测文件.类和函数,还可支持执行部分用例:Modula ...
- Ubuntu 20.24 安装Postgresql 14
1.运行环境 WSL+Ubuntu 20.04 2.安装Postgresql 进入Linux命令行,参照Postgresql官网安装指南 # Create the file repositor ...
- [BUUCTF]HCTF 2018WarmUp1 write up
ctrl+U查看源代码, 如下: 访问提示中的source.php文件 发现显示了源码,且存在另一个PHP文件hint.php(提示.php),先查看文件内是否有信息 用file来传参,并且要绕过wh ...
- NTP同步时间
什么是NTPNTP:Network Time Protocol(网络时间协议) ️ NTP 是用于同步网络中计算机时间的协议.它的用途是把计算机的时钟同步到世界协调时UTC. UTC:Universa ...
- gRPC之.Net6中的初步使用说明
1.介绍 GRPC是一个高性能.通用的开源远程过程调用(RPC)框架,基于底层HTTP/2协议标准和协议层Protobuf序列化协议开发,支持众多的开发语言,由Google开源. gRPC也是基于以下 ...
- PGF 概率生成函数 Probability generating function
Probability Mass Function 离散随机变量的分布函数PMF 目录 随机结构举例 two classical combinatorial distributions PGF Pro ...
- Ocelot使用与设置路由Routing
一.安装Ocelot 在程序包管理器控制台输入以下命令安装Ocelot Install-Package Ocelot 二.新建两个项目 我们新建两个.Net Core WebAPI项目如下: 直接 ...
- Hugging News #0317: ChatGLM 会成为 HF 趋势榜的第一名吗?
每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...
- C# 动态创建类,动态创建表,支持多库的数据库维护方案
1.创建表 SqlSugar支持了3种模式的建表,非常的灵活,可以MYSQL MSSQL ORACLE等用同一语法创建数据库,不需要考虑数据库的兼容性 中间标准: string 大文本 5.1.3. ...