最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

环球新动态:C# 闭包类对弱引用的坑

来源:博客园

闭包、弱引用的简单概念,大佬们描述的很多,我引用下:

  • 理解C#中的闭包 - 黑洞视界 - 博客园 (cnblogs.com)
  • C#弱引用(WeakReference) - 简书 (jianshu.com)

组里小伙伴报了个BUG,定义的封装事件DeviceDown不生效了


(资料图片仅供参考)

瞅了下,貌似没啥问题,单元测试、Demo都是okay的

虽然基本确认是业务层代码调用方面的问题,但还是要继续查根本原因

然后发现,弱引用WeakRefrence中的Target为Null了。

了解WeakRefrence的都知道,Null值代表对象被回收掉了。

剥离部分代码后,发现只剩下一个类SelectionBoxSingleEventor、一个相关初始化方法,我简化了下:

1     ///  2     /// 初始化选择框区域事件传递 3     ///  4     ///  5     ///  6     ///  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     ///  2     /// 对象是否支持弱引用 3     ///  4     ///  5     ///  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”。

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

关键词: 自动回收 是否支持 一段时间