如何事件会导致在C#中的内存泄漏以及如何弱引用有助于减轻? [英] How do events cause memory leaks in C# and how do Weak References help mitigate that?

查看:317
本文介绍了如何事件会导致在C#中的内存泄漏以及如何弱引用有助于减轻?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有两种方式(即我所知道的),使在C#中的意外内存泄漏:

There are two ways (that I know of) to cause an unintentional memory leak in C#:

  1. 在不配置实现资源的IDisposable
  2. 引用和取消引用的事件不正确。

我真的不明白的第二个点。如果源对象具有更长的寿命比监听器和监听器不需要事件时,再没有其他的引用它,使用普通的.NET事件导致内存泄漏:源对象保存在内存中监听对象应垃圾回收。

I don't really understand the second point. If the source object has a longer lifetime than the listener, and the listener doesn't need the events anymore when there are no other references to it, using normal .NET events causes a memory leak: the source object holds listener objects in memory that should be garbage collected.

您能否解释一下事件是如何导致在C#与code内存泄漏,我怎么能code。使用弱引用和不弱引用避开它?

Can you explain how events can cause memory leaks with code in C#, and how I can code to get around it using Weak References and without Weak References?

推荐答案

在一个监听器附加的事件侦听器的事件,源对象将获得一个引用侦听器对象。这意味着,听者不能被垃圾收集器收集直到该事件处理程序被分离,或源对象被收集

When a listener attaches an event listener to an event, the source object will get a reference to the listener object. This means that the listener cannot be collected by the garbage collector until either the event handler is detached, or the source object is collected.

考虑如下的类:

class Source
{
    public event EventHandler SomeEvent;
}

class Listener
{
    public Listener(Source source)
    {
        // attach an event listner; this adds a reference to the
        // source_SomeEvent method in this instance to the invocation list
        // of SomeEvent in source
        source.SomeEvent += new EventHandler(source_SomeEvent);
    }

    void source_SomeEvent(object sender, EventArgs e)
    {
        // whatever
    }
}

...然后将下面的code:

...and then the following code:

Source newSource = new Source();
Listener listener = new Listener(newSource);
listener = null;

即使我们给监听器,将没有资格进行垃圾回收,因为 newSource的仍持有的引用,事件处理程序( Listener.source_SomeEvent )。要解决这种泄漏,当不再需要它们永远分离事件监听器是很重要的。

Even though we assign null to listener, it will not be eligible for garbage collection, since newSource is still holding a reference to the event handler (Listener.source_SomeEvent). To fix this kind of leak, it is important to always detach event listeners when they are no longer needed.

上面的样品被写入注重与泄漏的问题。为了解决这个问题code,最简单的也许会是让监听器上引用坚持来源,因此,它可以在以后分离事件侦听器:

The above sample is written to focus on the problem with the leak. In order to fix that code, the easiest will perhaps be to let Listener hold on to a reference to Source, so that it can later detach the event listener:

class Listener
{
    private Source _source;
    public Listener(Source source)
    {
        _source = source;
        // attach an event listner; this adds a reference to the
        // source_SomeEvent method in this instance to the invocation list
        // of SomeEvent in source
        _source.SomeEvent += source_SomeEvent;
    }

    void source_SomeEvent(object sender, EventArgs e)
    {
        // whatever
    }

    public void Close()
    {
        if (_source != null)
        {
            // detach event handler
            _source.SomeEvent -= source_SomeEvent;
            _source = null;
        }
    }
}

然后调用code可以表明它正在使用的对象,这将删除引用来源有'Listener`做;

Then the calling code can signal that it is done using the object, which will remove the reference that Source has to ´Listener`;

Source newSource = new Source();
Listener listener = new Listener(newSource);
// use listener
listener.Close();
listener = null;

这篇关于如何事件会导致在C#中的内存泄漏以及如何弱引用有助于减轻?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆