【问题标题】:Memory leak Directory.GetFiles() VB.NET内存泄漏 Directory.GetFiles() VB.NET
【发布时间】:2012-12-20 19:05:07
【问题描述】:

我编写了一个启动器实用程序,它使用Timer 上的Directory.GetFiles() 来跟踪开始菜单中的快捷方式。

但是,它存在内存泄漏。我没有做任何奇怪的事情,所以我不明白为什么它会泄漏......我让程序保持打开状态,几天后,它达到了 300mb。我使用 CLR Profiler 试图定位泄漏,它说内存泄漏来自 Directory.GetFilesDirectory.GetFileNameWithoutExtension 分配的 String 实例这是我正在使用的代码:

Private Sub tmr_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tmr.Tick
    IndexStartMenu()
    GC.Collect()
End Sub

Private Sub IndexStartMenu()

    Dim startMenu As IO.DirectoryInfo
    Dim shortcuts() As IO.FileInfo

    'Enumerate current user's start menu
    startMenu = New IO.DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu))
    shortcuts = startMenu.GetFiles("*.lnk", IO.SearchOption.AllDirectories)
    For Each lnk As IO.FileInfo In shortcuts
        Dim newRow As DataRow = dtApps.NewRow
        newRow("Application") = IO.Path.GetFileNameWithoutExtension(lnk.FullName)
        newRow("Window") = "Launch"
        newRow("Hwnd") = ""
        newRow("IsShortcut") = True
        newRow("ShortcutPath") = lnk.FullName
        dtApps.LoadDataRow(newRow.ItemArray, LoadOption.Upsert)
        newRow = Nothing
    Next

    'Enumerate all users' start menu
    startMenu = New IO.DirectoryInfo(allUsersStartMenuPath)
    shortcuts = startMenu.GetFiles("*.lnk", IO.SearchOption.AllDirectories)
    For Each lnk As IO.FileInfo In shortcuts
        Dim newRow As DataRow = dtApps.NewRow
        newRow("Application") = IO.Path.GetFileNameWithoutExtension(lnk.FullName)
        newRow("Window") = "Launch"
        newRow("Hwnd") = ""
        newRow("IsShortcut") = True
        newRow("ShortcutPath") = lnk.FullName
        dtApps.LoadDataRow(newRow.ItemArray, LoadOption.Upsert)
        newRow = Nothing
    Next

    'Trying to fix memory usage
    startMenu = Nothing
    Array.Clear(shortcuts, 0, shortcuts.Length)
    shortcuts = Nothing
End Sub

【问题讨论】:

  • 确保部署您的 Release 版本。 vb.net 应用程序的调试版本在没有附加调试器的情况下运行时泄漏。
  • 不,没有区别。
  • 哇,那几天一晃而过。没有任何方法可以在 17 分钟内看到。
  • 大声笑,出于测试目的,我将计时器间隔从 60,000 毫秒更改为 20 毫秒。
  • 您检索到的字符串被放入数据表 dtApps 中,该数据表不在 Sub 的范围内。也许那些还在某处被引用?

标签: vb.net memory-leaks


【解决方案1】:

根据您发布的方法,计时器不会每隔一段时间触发一次并重复添加这些目录的内容吗?如果 dtApps 是一个范围为在应用程序期间持续存在的类的 DataTable 字段,那么您只是重复地将行添加到 DataTable 导致它增长。这不是内存泄漏,而是自然事件。检查 dtApp 的行数。我的猜测是您打算只添加新行。

此外,您可以改进上述解决方案,并通过使用FileSystemWatcher 消除基于计时器轮询两个目录的需要。当文件系统发生更改时,FileSystemWatcher 将通过触发事件来通知您。

【讨论】:

  • 似乎带有Upsert 参数的LoadDataRow 应该处理重复项。
  • 我相信这取决于数据表的 PK 是什么。如果没有指定,我认为每次调用 LoadDataRow 都会导致插入。 LoadDataRow 期望 PK 字段将出现在传递给它的数据中。查看 DataTable 的定义和/或行数可能有助于回答这个问题,如果这是可能发生的事情。
  • Calvin 是正确的,这就是我指定 upsert 参数的原因。在 CLR Profiler 中,与 DataTable 相关的内存可以忽略不计。问题是在 Directory.GetFiles() 方法中创建的字符串似乎不是垃圾收集...
猜你喜欢
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 2011-10-08
  • 2013-01-20
  • 2011-10-31
  • 2019-08-10
  • 2013-06-24
相关资源
最近更新 更多