闭包、弱引用的简单概念,大佬们描述的很多,有不了解的可以看看:

组里小伙伴报了个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# 闭包类对弱引用的坑的更多相关文章

  1. Java中弱引用、软引用、虚引用及强引用的区别

    Java中弱引用VS软引用 Java中有如下四种类型的引用: 强引用(Strong Reference) 弱引用(WeakReference) 软引用(SoftReference) 虚引用(Phant ...

  2. weakref:对象的弱引用

    介绍 weakref支持对象的弱引用,正常的引用会增加对象的引用计数,并避免它被垃圾回收.但结果并不是总和期望的那样,比如有时候可能会出现一个循环引用,或者有时候需要内存时可能要删除对象的缓存.而弱引 ...

  3. 初解C#类、结构、弱引用

    一.类 类中的数据和函数称为类的成员 数据成员是包含类的数据----字段.常量和事件的成员.数据成员可以是静态数据.类成员总是实例成员,除非用static进行显示的声明. 事件是类的成员,在发生某些行 ...

  4. android WeakReference(弱引用 防止内存泄漏)与SoftReference(软引用 实现缓存机制(cache))

    在Android开发中,基本上很少有用到软引用或弱引用,这两个东东若用的很好,对自己开发的代码质量的提高有很大的帮助.若用的不好,会坑了自己.所以,在还没有真正的去了解它们之前,还是慎用比较好. 下面 ...

  5. 弱引用?强引用?未持有?额滴神啊-- Swift 引用计数指导

    ARC ARC 苹果版本的自动内存管理的编译时间特性.它代表了自动引用计数(Automatic Reference Counting).也就是对于一个对象来说,只有在引用计数为0的情况下内存才会被释放 ...

  6. IOS 看懂此文,你的block再也不需要WeakSelf弱引用了!

    前言: 最近都在折腾 Sagit 架框的内存释放的问题,所以对这一块有些心得. 对于新手,学到的文章都在教你用:typeof(self) __weak weakSelf = self. 对于老手,可能 ...

  7. Python引用复制,参数传递,弱引用与垃圾回收

    引用 先上个示例: >>> val = [1] >>> val[0] = val >>> val [[...]] 上述代码使val中包含自身,而产 ...

  8. c++弱引用与强引用

    https://www.zhihu.com/question/26851369 智能指针一个很重要的概念是"所有权",所有权意味着当这个智能指针被销毁的时候,它指向的内存(或其它资 ...

  9. Android 弱引用和软引用

    软引用 和 弱引用 1.  SoftReference<T>:软引用-->当虚拟机内存不足时,将会回收它指向的对象:需要获取对象时,可以调用get方法. 2.  WeakRefere ...

随机推荐

  1. Otto Group Product Classification

    遇到的坑: 做多分类,用CrossEntropyLoss时,训练时候的正确标签的范围应该是[0,n-1],而不是[1,n],不然会报 IndexError: Target is out of boun ...

  2. ggplot axis text 拐弯

    scale_y_discrete(position = "left",labels=function(x) str_wrap(x, width=48)) +

  3. 异常:Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.3.2.RELEASE:repackage (repackage) 解决办法

    异常:Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.3.2.RELEASE:repackage ...

  4. MobaXterm注册认证版,亲测可用,操作简单(本机已安装python3环境)

    去github地址下下载代码 解压后在该目录下打开CMD 执行MobaXterm-Keygen.py <UserName> <Version>命令 生成的文件放在安装目录下,我 ...

  5. Spring bean注入问题:NoUniqueBeanDefinitionException解决方案归纳

    引言 spring实现的bean自动注入在项目开发中是一个经常使用到的功能,但自动装配两个或多个bean时,会抛出NoUniqueBeanDefinitionException:No qualifyi ...

  6. Rancher 通过主机标签进行调度

    https://blog.csdn.net/qq12547345/article/details/121486709

  7. mysql 死锁解决

    查看锁记录等待时间: SHOW VARIABLES LIKE 'innodb_lock_wait_timeout'; 把超时等待时间修改为5秒: SET innodb_lock_wait_timeou ...

  8. 【Beat】Scrum Meeting 4

    时间:2021年6月29日 1.各个成员今日完成的任务以及贡献小时数 姓名 今日完成任务 贡献小时数 鑫 继续进行bug的修改 4 荣娟 继续进行bug的修改 4 亚楠 继续进行bug的修改 4 桂婷 ...

  9. spring-dao.xml

    本文件的作用:1整合dao层,连接数据库 2设置数据库连接池3配置SqlSessionFactory对象4配置扫描Dao接口包,动态实现dao接口,注入到spring容器中 Ps:此文件可以替代myb ...

  10. ssh基于主机名访问

    登录一台服务器我们可以用ssh user@IP这种方式 还有一种快捷的方式,就是基于主机名访问,这需要先配置 /etc/hosts文件 假如我们又两台主机 192.168.75.131/165 分别为 ...