警惕C#事件使用过程中的GC陷阱
关于C#中的事件,园里已经有大量的文章对其内在实现做过剖析,如果还不甚了解的可以阅读这篇文章
通过Demo来细看C#事件的内在机制
虽然比较早,但非常清楚地展示了事件的内部机制,总结一下就是
1、事件在被编译后生成了一个事件对应类型的私有委托,以及对应的_add方法和_remove方法用于该私有委托的注册和取消注册,其实就是平时常用的“+=”和“-=”。正是由于这个原因,所以事件在外部只能通过_add和_remove来对其调用链进行修改,而不能直接使用“=”,这使得事件的封装性要优于委托(理论上特别符合观察者模式)。
2、当我们通过_add和_remove来订阅事件和取消订阅的时候,最终改变的是生成的私有委托,而改变所使用的方法就是System.Delegate的Combine()。当事件第一次被订阅时,会将null和被订阅的方法进行Comine,然后将返回值赋值给私有委托。在之后事件被订阅的时候,会将原有的委托和新的方法进行Combine,然后将返回值赋给原委托。(这里非常像使用+对字符串进行拼接)
根据这个机制,不难想到一个问题,既然事件的订阅和取消最终采用的是Combine方法,而Combine方法又是通过生成新的委托然后返回的方式来实现的,如果事件的订阅者很多很多,又或者订阅和取消操作进行得非常频繁,是不是会影响到GC?答案是肯定的。
我做了一个简单的测试

像上面这样的代码,Test方法中的GC达到了0.5m,虽然像这样的代码比较极端,但也充分说明了,如果一个事件被频繁的订阅和取消,这里面产生的GC绝对是不容忽视的。就如同大家都知道不要大量和频繁地使用“+”来拼接字符串一样,对于事件,在订阅列表会频繁变化的时候,建议可以通过自行封装一个委托列表来达到和事件类似的效果,通过列表的Add和Remove来添加和去除委托,那样产生的GC基本就可以忽略不计了。
警惕C#事件使用过程中的GC陷阱的更多相关文章
- ESXi与物理交换机静态链路聚合配置过程中的小陷阱
作者:陆斌文章来自微信公众号:平台人生 内容简介:ESXi与物理交换机之间配置静态链路聚合时,因为静态链路聚合的特点,在进行down网卡和从虚拟交换机移除网卡的操作时,可能会无法完成故障流量切换,影响 ...
- robot framework程序运行过程中,遇到点击事件之后,未出现点击之后的效果(求解)
1.click Element操作,在实际过程中偶然会出现,日志显示已点击成功,但是实际自动化页面,没有点击成功之后的操作 现象: 现象描述:程序执行到点击侧边栏的[人员信息]之后,日志显示已经点击成 ...
- ajax用beforeSend自定义请求过程中客户端事件,提高用户体验
本文为博主原创,未经允许不得转载: 在应用ajax的过程中,当我们再前台提交请求的时候,如果服务端响应事件比较长,就会导致需要等很长时间在前台才能接受到服务端返回的 响应结果,往往会导致用户重复点击按 ...
- Unity中的GC以及优化
[简介] 常见的 Unity GC 知识点总结出来的思维导图 Unity 官方文档,正巧在博客园发现了已经有位大神(zblade)把原文翻译出来了,而且质量很高~,译文地址 在这里.下面我就可耻地把译 ...
- 浅谈Unity中的GC以及优化
介绍: 在游戏运行的时候,数据主要存储在内存中,当游戏的数据不在需要的时候,存储当前数据的内存就可以被回收再次使用.内存垃圾是指当前废弃数据所占用的内存,垃圾回收(GC)是指将废弃的内存重新回收再次使 ...
- 不得不知的CLR中的GC
引言 GC 作为CLR的垃圾回收器,让程序员可以把更多的关注度放在业务上而不是垃圾回收(内存回收)上.其实很多语言也有类似的东东, 如Java也有JIT 等等 GC基本概念 垃圾回收机制的算法有好多种 ...
- View的绘制、事件传递过程
View绘制过程 onMeasure() onLayout() onDraw() 过程详解 onMeasure() 计算尺寸 onLayout() 为viewGroup类型布局子视图用的. onDra ...
- 背水一战 Windows 10 (21) - 绑定: x:Bind 绑定, x:Bind 绑定之 x:Phase, 使用绑定过程中的一些技巧
[源码下载] 背水一战 Windows 10 (21) - 绑定: x:Bind 绑定, x:Bind 绑定之 x:Phase, 使用绑定过程中的一些技巧 作者:webabcd 介绍背水一战 Wind ...
- 使用JSF框架过程中的若干典型问题及其解决方案
1.commandXxx点击后,不调用action中的方法: 原因1:xhtml后缀名的文件,最终也会转化为普通的html文件(这是熟悉JSF框架的关键.),commandXxx点击后不调用后台act ...
随机推荐
- RHEL6 64位ASM方式安装oracle 11gR2(二)
本文转载自:http://vnimos.blog.51cto.com/2014866/1221377 三.安装数据库软件 1 2 3 4 5 6 7 8 # unzip -d /stage/ linu ...
- 网络编程Socket之wireshark使用
这里只对wireshark进行简单的使用介绍.里面的报表,IO图形分析等以后再谈.... 这里不提供下载地址了,不是什么稀有资源,我使用的wireshark是在百度软件中心下载的. 第一步:选择需要 ...
- php对数组中的值进行排序
案例 <?php $a = array('1124','1125','1126'); $s1 = 1124; $s2 = 1125; $ks1 = array_search($s1,$a); $ ...
- matlab神经网络工具箱创建神经网络
为了看懂师兄的文章中使用的方法,研究了一下神经网络 昨天花了一天的时间查怎么写程序,但是费了半天劲,不能运行,百度知道里倒是有一个,可以运行的,先贴着做标本 % 生成训练样本集 clear all; ...
- 关于datatable对象的用法
在项目中经常用到DataTable,如果DataTable使用得当,不仅能使程序简洁实用,而且能够提高性能,达到事半功倍的效果,现对DataTable的使用技巧进行一下总结. 一.DataTable简 ...
- JavaScript第二节
1.动态属性 引用类型可以动态的添加属性,而基本类型不行. 2.复制变量值 3.检测类型 执行环境和作用域 没有块级作用域 引用类型 1.Object类型 2.Array类型 数组初始化: 检测数组: ...
- Spring Cloud Zuul 2(基于配置中心的动态API网关)
在大体了解了API Zuul 和 配置中心Config后我们来尝试完成一个基于配置中心的动态API网关 创建项目 命名为api-gateway-dynamic-route并加入config 和 Zuu ...
- jenkins 学习记录2
主题 在之前的学习中(http://www.cnblogs.com/abcwt112/p/6274575.html)我已经学会怎么打包了..这篇文章记录分享我学习如何利用jenkins将打完的包发布到 ...
- Android Architecture Components
https://developer.android.com/topic/libraries/architecture/index.html ViewModel 有LiveData Activity 监 ...
- 【光速使用开源框架系列】数据库框架OrmLite
[关于本系列] 最近看了不少开源框架,网上的资料也非常多,但是我认为了解一个框架最好的方法就是实际使用.本系列博文就是带领大家快速的上手一些常用的开源框架,体会到其作用. 由于作者水平有限,本系列只会 ...