关于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陷阱的更多相关文章

  1. ESXi与物理交换机静态链路聚合配置过程中的小陷阱

    作者:陆斌文章来自微信公众号:平台人生 内容简介:ESXi与物理交换机之间配置静态链路聚合时,因为静态链路聚合的特点,在进行down网卡和从虚拟交换机移除网卡的操作时,可能会无法完成故障流量切换,影响 ...

  2. robot framework程序运行过程中,遇到点击事件之后,未出现点击之后的效果(求解)

    1.click Element操作,在实际过程中偶然会出现,日志显示已点击成功,但是实际自动化页面,没有点击成功之后的操作 现象: 现象描述:程序执行到点击侧边栏的[人员信息]之后,日志显示已经点击成 ...

  3. ajax用beforeSend自定义请求过程中客户端事件,提高用户体验

    本文为博主原创,未经允许不得转载: 在应用ajax的过程中,当我们再前台提交请求的时候,如果服务端响应事件比较长,就会导致需要等很长时间在前台才能接受到服务端返回的 响应结果,往往会导致用户重复点击按 ...

  4. Unity中的GC以及优化

    [简介] 常见的 Unity GC 知识点总结出来的思维导图 Unity 官方文档,正巧在博客园发现了已经有位大神(zblade)把原文翻译出来了,而且质量很高~,译文地址 在这里.下面我就可耻地把译 ...

  5. 浅谈Unity中的GC以及优化

    介绍: 在游戏运行的时候,数据主要存储在内存中,当游戏的数据不在需要的时候,存储当前数据的内存就可以被回收再次使用.内存垃圾是指当前废弃数据所占用的内存,垃圾回收(GC)是指将废弃的内存重新回收再次使 ...

  6. 不得不知的CLR中的GC

    引言 GC 作为CLR的垃圾回收器,让程序员可以把更多的关注度放在业务上而不是垃圾回收(内存回收)上.其实很多语言也有类似的东东, 如Java也有JIT 等等 GC基本概念 垃圾回收机制的算法有好多种 ...

  7. View的绘制、事件传递过程

    View绘制过程 onMeasure() onLayout() onDraw() 过程详解 onMeasure() 计算尺寸 onLayout() 为viewGroup类型布局子视图用的. onDra ...

  8. 背水一战 Windows 10 (21) - 绑定: x:Bind 绑定, x:Bind 绑定之 x:Phase, 使用绑定过程中的一些技巧

    [源码下载] 背水一战 Windows 10 (21) - 绑定: x:Bind 绑定, x:Bind 绑定之 x:Phase, 使用绑定过程中的一些技巧 作者:webabcd 介绍背水一战 Wind ...

  9. 使用JSF框架过程中的若干典型问题及其解决方案

    1.commandXxx点击后,不调用action中的方法: 原因1:xhtml后缀名的文件,最终也会转化为普通的html文件(这是熟悉JSF框架的关键.),commandXxx点击后不调用后台act ...

随机推荐

  1. 1088 Rational Arithmetic

    题意: 给出两个分式(a1/b1 a2/b2),分子.分母的范围为int型,且确保分母不为0.计算两个分数的加减乘除,结果化为最简的形式,即"k a/b",其中若除数为0的话,输出 ...

  2. 1052 Linked List Sorting

    题意:链表排序 思路:题目本身并不难,但是这题仔细读题很重要.原题中有一句话,"For each case, the first line contains a positive N and ...

  3. 解决在“Resources”参数中指定了项“obj\Debug\KaiShiHID.Form1.resources”多次。“Resources”参数不支持重复项

    错误截图: 发生原因描述: 窗体Form1, 有一个分部类; 叫做FormPartial.cs; 双击了FormPartial这个窗体, 然后生成了一个Load事件, 即时就报了编译错误, 然后就删除 ...

  4. windows右键打开方式里面添加新的应用程序

    1.打开注册表编辑器.打开运行窗口,快捷键,开始+R.输入“regedit”,回车确定. 2.进入注册表编辑器的HKEY_CLASSES_ROOT文件夹下的*子文件夹下的shell文件夹. 3.右键s ...

  5. Select/Poll/Epoll异步IO

    IO多路复用 同步io和异步io,阻塞io和非阻塞io分别是什么,有什么样的区别? io模式 对于一次io 访问(以read为例),数据会先拷贝到操作系统内核的缓冲区,然后才会从操作系统内核的缓冲区拷 ...

  6. re模块练习

    1.匹配标签 1 import re 2 ret = re.search('<(?P<tag_name>\w+)>\w+</(?P=tag_name)>','< ...

  7. leetcode583

    public class Solution { public int MinDistance(string word1, string word2) { , word2.Length + ]; ; i ...

  8. Mybatis系列(四)映射文件

    转自:https://blog.csdn.net/chris_mao/article/details/48811507 Mybatis的真正强大,在于她对SQL的映射,这也是她吸引人的地方.实现相同的 ...

  9. centos7 时间设置及ntp

    转自:https://blog.gtwang.org/linux/howto-set-date-time-from-linux-command-prompt/ 這裡介紹各種在 Linux 中以手動來調 ...

  10. Java占位符替换工具类

    import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFact ...