.net - .NET 中由于事件处理程序导致内存泄漏的示例?

标签 .net events memory memory-leaks event-handling

人们一直在谈论由于未释放的事件监听器而发生的内存泄漏。我认为这是一个非常重要的问题。非常严肃,非常重要......如果它真的存在的话。

我尝试自己重现该问题,但所有尝试都失败了:我只是无法让我的应用程序泄漏内存:( 虽然听起来不错,但我仍然担心:也许我错过了一些东西。

那么也许有人可以提供一个非常简单的导致内存泄漏的源代码示例?

我创建了一个小型 VB.NET 应用程序作为演示:它包含一个 Windows 窗体和一个类。

Windows 窗体:它有一个集合对象(名为“c”)和两个按钮:一个用于向集合中添加 10 个项目,另一个用于清除集合:

Public Class Form1

Dim c As New Collection

Private Sub btnAddItem_Click(sender As System.Object, e As System.EventArgs) Handles btnAddItem.Click
    For i As Integer = 1 To 10
        Dim m As New MyType
        c.Add(m)
    Next

    Me.Text = c.Count
End Sub

Private Sub btnClear_Click(sender As System.Object, e As System.EventArgs) Handles btnClear.Click
    For Each item As MyType In c
        item.Dispose()
    Next
    c.Clear()

    Me.Text = c.Count
End Sub
End Class

MyType 类:它有一个很大的 m_Image 对象,它很大,所以你可以看到你的内存确实被 MyType 实例占用了:)

Imports System.Drawing

Public Class MyType 
Implements IDisposable

Private m_Image As Bitmap

Public Sub New()
    AddHandler Application.Idle, AddressOf Application_Idle

    m_Image = New Bitmap(1024, 1024)
End Sub

Private Sub Application_Idle(sender As Object, e As EventArgs)

End Sub

#Region "IDisposable Support"
Private disposedValue As Boolean

Protected Overridable Sub Dispose(disposing As Boolean)
    If Not Me.disposedValue Then
        If disposing Then
            m_Image.Dispose()
        End If
    End If
    Me.disposedValue = True
End Sub

Public Sub Dispose() Implements IDisposable.Dispose
    Dispose(True)
    GC.SuppressFinalize(Me)
End Sub
#End Region

End Class

最佳答案

这是一个非常简单的例子

class MyType
{
    public static event EventHandler ExampleEvent;

    public MyType()
    {
        ExampleEvent += (sender, e) => OnExampleEvent();
    }
    private void OnExampleEvent() { }
}

MyType 的任何实例都将订阅 ExampleEvent 事件。该事件不附加到任何特定对象,因此它永远不会离开内存。这将在应用程序运行期间将所有 MyType 实例保存在内存中。

编辑

正如评论中所要求的,这是 MyType 实例在不再使用后仍保留在内存中很长时间的演示

class Program
{
    static void Main(string[] args)
    {
        WeakReference weakRef = new WeakReference(new MyType());
        for (var i = 0; i < 10; i++)
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

        Console.WriteLine("Still Alive: {0}", weakRef.IsAlive);
    }
}

关于.net - .NET 中由于事件处理程序导致内存泄漏的示例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10056232/

相关文章:

javascript - 当脚本插入 DOM 时,jQuery .on() 未绑定(bind)

c++ - 使用 Xerces 从内存中加载 xml

java不安全,如何将内存解释为其他类型的对象?

pointers - 如果没有对所指向的值的共享引用,为什么取消引用原始指针会产生段错误?

c# - 等待完成所有异常处理任务

.net - 使用 nlog 在控制台应用程序中滚动文件日志

c# - 对象初始化和 "Named Constructor Idiom"

c# - 在可重用类中封装多个服务引用操作

javascript - 使用 Scriptaculous 拖放防止 JavaScript 单击事件

jquery - 元素.bind ("resize.container", function() { .. } );