首页 > 编程语言 >C# 闭包类对弱引用的坑

C# 闭包类对弱引用的坑

时间:2023-01-28 19:55:08浏览次数:54  
标签:闭包 return target 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”。

通过上面对类名称的分析,判断对象是否支持弱引用。不支持弱引用,直接使用事件即可(弱引用都不支持了,管他内存泄不泄漏。。。)

 

标签:闭包,return,target,C#,引用,闭包类
From: https://www.cnblogs.com/kybs0/p/17071176.html

相关文章

  • 3-reg model构建篇-uvm_reg_block
    1. uvm_reg_block的特点(1) 一个寄存器模型必须包含一个reg_block; 一般DUT内具有相同的基地址的所有寄存器,会放在一个reg_block中.(2) uvm_reg_block可以包含任意......
  • 【算法训练营day28】LeetCode93. 复原IP地址 LeetCode78. 子集 LeetCode90. 子集II
    LeetCode93.复原IP地址题目链接:93.复原IP地址独上高楼,望尽天涯想起来简单,写起来还是很难的一道题,小错误频发。慕然回首,灯火阑珊首先,因为本题要求只能分割成四段,所......
  • Java两大工具库:Commons和Guava(2)
    您好,我是湘王,这是我的51CTO博客。值此新春佳节,我给您拜年啦~祝您在新的一年中所求皆所愿,所行皆坦途,展宏“兔”,有钱“兔”,多喜乐,常安宁!开发中有一类应用会出现的比较多,就是文......
  • [ecstore]开启memcache缓存的ecstore,磁盘满了后,打开提示header function does not exi
    开启memcache缓存的ecstore,磁盘满了后,打开提示headerfunctiondoesnotexistin/home/wwwroot/xxxx/app/base/lib/component/compiler.phponline368的解决方法1、先......
  • Java两大工具库:Commons和Guava(2)
    您好,我是湘王,这是我的博客园。值此新春佳节,我给您拜年啦~祝您在新的一年中所求皆所愿,所行皆坦途,展宏“兔”,有钱“兔”,多喜乐,常安宁!   开发中有一类应用会出现的比较......
  • 常用命令(cmd和dos)
    CMD:运行win+rshift+右键打开命令行窗口文件夹地址栏中输入cmd管理员方式打开常用的dos命令:#盘符切换:d:e:...#查看当前目录下所有文件:dir#切换目录:cd......
  • BUUCTF 假如给我三天光明(经典盲文+摩斯密码)
    泪目:我当时因为看这部小说后面老师与海伦之间的感情看哭了,我现实中也遇到过这样的老师,经常能跟她开玩笑,互怼,有问题直接问,关系非常要好那种!!嘿嘿嘿 话不多说,直接看题吧!......
  • ethcat开发记录 三
    一、关于controlword的控制1514131211109876543210保留待定暂停故障复位模式有关伺服使能快停上电伺服准备好   ......
  • 通过 eShopOnContainers 项目学习一下微服务
    这里是项目地址https://github.com/dotnet-architecture/eShopOnContainers,这是微软创建的一个基于.NET平台的微服务架构的示例应用程序,里面基本上市面上主流的时髦的......
  • Data Processing code sample :
    DataProcessingcodesample:Scala:https://github.com/awslabs/deequpython:https://github.com/awslabs/python-deequ......