美文网首页程序员
内存泄漏之Static Event

内存泄漏之Static Event

作者: 古意昌 | 来源:发表于2018-01-17 19:38 被阅读0次

静态类里面的事件,再普通不过,经常使用它来做全局广播。
但是如果一不小心就会发生内存泄漏,请看下面的Demo:
我创建了一个简单的窗口Example4.xaml:

<Window x:Class="MemoryLeak.Example.Example4"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Window>

Example4.xaml.cs中的代码如下:

public partial class Example4 : Window
{
    //这里产生一个大的内存占用,约50MB,用于在任务管理器看到这个窗口Show出来以后,进程内存占用剧增的现象
    private readonly List<string> _bigList = ExampleHelper.BigList();
 
    public Example4()
    {
        InitializeComponent();

        ExampleHelper.LeakEvent += ExampleHelper_LeakEvent;
    }

    private void ExampleHelper_LeakEvent(object sender, System.EventArgs e)
    {
        Console.WriteLine(DateTime.Now);
    }
}

public static class ExampleHelper
{
    public static event EventHandler LeakEvent;
}

内存泄漏现象

Example4 window = new Example4();
window.Show();

然后将此window直接关闭,那么显然这个window生命周期结束,再无引用。执行:

GC.Collect();

window占用的50MB内存应该被回收,然后在任务管理器中看此进程,其内存并没有被回收。什么东西阻止了我回收?阻止回收的根本原因是仍然有人引用!我们来挖一下,深层次的原因在哪里。

源码分析

window生命周期分析

我们仔细看一下这个代码ExampleHelper.LeakEvent += ExampleHelper_LeakEvent;,这句代码的完整形式应该是ExampleHelper.LeakEvent += this.ExampleHelper_LeakEvent;我们知道事件的工作原理是观察者模式,要实现观察者模式就必须有目标Target和处理函数Method,那么ExampleHelper.LeakEvent += ExampleHelper_LeakEvent;这句话将this作为观察者模式中的Target,ExampleHelper_LeakEvent作为Method,当事件发生的时候可以通过Target调用Target中的Method,所以ExampleHelper.LeakEvent += ExampleHelper_LeakEvent;这句话就将window强引用了。而这个事件是个static变量哦,什么是staticstatic对象就是生命周期跟进程的生命周期同样长的对象。

image.png

内存泄漏原因深度剖析及解决措施

上述问题谈到ExampleHelper.LeakEvent += ExampleHelper_LeakEvent;,这句代码造成了对window的强引用,所以你不用的的时候需要手动解除一下引用关系:ExampleHelper.LeakEvent -= ExampleHelper_LeakEvent;,这样就可以回收了。
但是:
如果我们换一种办法:ExampleHelper.LeakEvent += (s, e) => { Console.WriteLine(DateTime.Now); };,这样会不会造成window无法被回收呢?答案是不回,但是如果是这样:ExampleHelper.LeakEvent += (s, e) => { Console.WriteLine(this.Width); };,那么window无法被回收。匿名函数到底发生了什么?为什么有时会阻止回收,有时不会?请看我的另一篇文章:《原来是这样:C#中的匿名函数 & 闭包(未完成)》

至此static event 造成的内存泄漏分析完毕,我们知晓了造成内存泄漏的根本原因就是还有引用,解决措施就很简单了:在不需要的时候解除引用。

相关文章

  • 内存泄漏之Static Event

    静态类里面的事件,再普通不过,经常使用它来做全局广播。但是如果一不小心就会发生内存泄漏,请看下面的Demo:我创建...

  • Android static 内存泄漏场景

    内存泄漏: 静态对象内存泄漏 static Object cc=null 在Dalvik虚拟机中,static变量...

  • Android Knowledge

    一. 系统优化 1.1 内存泄漏优化 1.1.1 静态变量导致内存泄漏 public static Contex...

  • 内存泄漏之Event Handler

    事件是我们在WPF开发过程中使用的非常多的技术,但是如果一不小心就会发生内存泄漏,请看下面的Demo。我创建了一个...

  • Android Dev 课程作业 - 内存泄漏

    activity的 static 成员 造成的内存泄漏static TestView sTextView 由于要s...

  • C#内存泄漏:Event内存泄漏

    前言 内存泄漏是指:当一块内存被分配后,被丢弃,没有任何实例指针指向这块内存, 并且这块内存不会被GC视为垃圾进行...

  • android内存泄露

    参考内存泄露从入门到精通三部曲之基础知识篇Android 内存泄漏总结Android内存泄漏研究Android内存...

  • 【Android测试】内存泄漏检测 LeakCanary

    什么是内存泄漏和内存溢出?内存泄漏有什么危害?LeakCanary检测内存泄漏? 内存泄漏(Memory Leak...

  • Handler的正确使用姿势

    为了避免因为handler持有activity导致的内存泄漏 可以将内部类写成静态内部类 static class...

  • 【Android】内存泄漏—static成员变量

    (1)static内存泄漏 1、static修饰的成员变量的生命周期和整个应用程序的生命周期一致2、例如stati...

网友评论

    本文标题:内存泄漏之Static Event

    本文链接:https://www.haomeiwen.com/subject/mnnuoxtx.html