4

我知道这是一个热门话题,有很多问题和答案,但我仍然找不到以下问题的解决方案:

我有一个多标签应用程序。每个选项卡上都有一个 Webbrowser 控件。由于网络浏览器为每个新选项卡占用更多内存并且它们不会在选项卡关闭时释放此内存,因此我决定在选项卡关闭事件处理程序中创建一个 Webbrowser.Dispose()。这帮助我解决了内存泄漏问题。关闭后,所有使用的 RAM 现在都是空闲的。

但这引起了一个新问题:在第一个 Dispose() 之后,似乎所有其他 Webbrowser 对象的会话都被破坏了。通常我只登录到第一个网络浏览器。如果我添加几个标签,我通常会自动登录。在第一次 Dispose() 之后,这不再起作用,我必须在每个新选项卡上登录。

我试图保留旧的 cookie 并使用新的网络浏览器再次发送它们,但这并没有解决问题。似乎被摧毁了。

4

3 回答 3

2

这似乎是一个垃圾收集器问题。您可以尝试使用System.GC.Collect()的脏方法,只是调用 GarbageCollector 来释放内存,但这不是解决问题的好方法。

你所说的,这似乎是一个指针问题。如果您将 Connection 声明为全局变量,则必须从选项卡中分离连接,然后才能关闭/处置选项卡本身。Me.Closing事件可以帮助您这样做。如果指针保持打开状态,则作为对象的选项卡仍连接在 Connection 上,并且不会被 GC 清理(不是真的 shure if/when )。

如果您可以阐明复制/引用连接的方式,我可以给出更详细的答案。

编辑:经过一段时间的研究,我的担忧变成了现实——在 IE 下缓存存在问题(据我所知>5)。http://social.msdn.microsoft.com/Forums/ie/en-US/88c21427-e765-46e8-833d-6021ef79e0c8/memory-leak-in-ie-webbrowser-control

建议是:

  • 手动调用 GarbageCollector

  • 限制 MemUsage(可能导致应用程序崩溃,也只是将页面写入磁盘)

  • about:blanc 覆盖缓存条目

  • 调用 C++ 方法来覆盖缓存(WinINet - 我发现的所有结果都导致了一些 ProtectedMemory-Errors - 也许这个C# WebBrowser 控件:清除缓存而不清除 cookie有效)

  • 使用 C++ 和 WinINet(我不知道任何真正的 .Net 实现,它也可能有这种内存泄漏)

  • 使用 IE 的替代品,例如 gecko (Mozilla) - https://bitbucket.org/geckofx/

于 2013-08-05T11:46:50.447 回答
2

所有 WebBrowser 实例在每个进程的基础上共享会话。根据EricLaw对类似问题的回答,似乎不可能分开会话。我相信 Eric 的说法,因为他在 Microsoft 担任 IE 项目经理

但是,如果您仍然想尝试一些技巧,可以查看CoInternetGetSession。首先,尝试保存并保留返回的对IInternetSession的引用。此外,您可以查看注册您自己的 URL 命名空间 ( RegisterNameSpace ) 并实现一个可插入的协议处理程序,该处理程序最终可能允许推翻此限制。

当然,这听起来有点矫枉过正,很可能根本无济于事。一个干净的解决方案可能是重新设计逻辑以摆脱 cookie 并通过 URL 传递状态。

已编辑:另一个想法,尝试将 WebBrowser 实例导航到(例如)“about:blank”并等待 DocumentComplete 事件,然后再使用 Dispose() 实际处理它。

于 2013-08-05T11:40:54.097 回答
1

感谢您的回答。这是我检查的内容:

手动调用 GC:

  • 仅在我之前使用 Webbrowser.Dispose() 时才有帮助。但是由于会话问题,这不是解决方案。

限制内存使用:

  • 不是解决方案。该程序应该运行一整天,并打开和关闭许多选项卡。如果我无法清理使用过的内存,那么几个小时后内存使用量会太多..

关于:空白:

  • 我在关闭选项卡时调用了 about:blank。在此 URL 发生 DocumentLoaded 后,我处置了 Webbrowser。与直接调用 Dispose 的过程相同。会话中断。

其他组件:

  • 我需要在每种情况下都有一个 IE 控件,因为(专有)互联网应用程序仅支持 IE 8 及更高版本。

“使用 c++ 和 WinInet”:

  • 我可以在我的 .net 程序中使用 C++ 浏览器吗?我无法将整个程序切换到 C++。这对我来说不是解决方案。

总之:

我的应用程序在没有 Dispose 的情况下工作正常,但内存使用量增加时出现问题。如果我们能找到解决方案(这似乎是不可能的),那将是最好的解决方案。

对我来说唯一可以接受的“解决方法”是重用“封闭”的网络浏览器。详细说明:在每个选项卡关闭时,我都会将 Webbrowser 添加到列表中,而不是 Dispose 它们。当我需要一个新选项卡时,我会从列表中取出第一个并重新使用它并导航到新的 URL:我试过了,但会话似乎存在同样的问题。重用选项卡中的会话似乎又是新的。但我真的不明白为什么......对此也有建议吗?

另一种解决方法是强制每个 Webbrowser 对象为单个实例。这可能吗?

于 2013-08-05T18:19:28.080 回答