【问题标题】:.NET Webbrowser Control and Dispose().NET Web 浏览器控制和 Dispose()
【发布时间】:2013-08-06 00:24:11
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我建议你先弄清楚你是否真的有问题。内存使用量是否变得如此之大以至于导致系统分页?是物理内存使用量增加还是仅虚拟内存增加?

标签: c# .net session webbrowser-control dispose


【解决方案1】:

所有 WebBrowser 实例在每个进程的基础上共享会话。根据EricLaw's answer 的类似问题,似乎不可能分开会话。我相信 Eric 的声明是he worked as IE program manager at Microsoft

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

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

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

【讨论】:

  • 我什么时候应该调用 about:blank?我应该在关闭标签页还是打开新标签页时调用它?
  • 在关闭选项卡并执行 webBrowser.Dispose() 之前。然后它可能(我希望)为其他标签保留会话。确保在调用 Dispose() 之前发生“about:blank”的 DocumentComplete。
  • 我检查了这个,但它不起作用:(。在我再次添加新标签后,应用程序要求登录
  • 如果您将 webBrowser 导航到 about:blank 但不处理它,它是否会提高内存使用率?
  • No 不会提高内存使用率,但在 about:blank 之后我也有会话问题。表示:网站要求再次登录
【解决方案2】:

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

手动调用GC:

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

限制内存使用:

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

关于:空白:

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

其他组件:

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

《使用c++和WinInet》:

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

总结:

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

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

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

【讨论】:

  • 您是否从 C# 访问任何内部 DHTML 或 JavaScript 对象(通过 webBrowser.InvokeScript 或 webBrowser.Document)?这可能会导致托管对象和 COM 对象之间的循环引用,并可能解释内存使用量增长的原因。
  • 不,我对 HTML 文档什么都不做。
【解决方案3】:

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

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

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

编辑:经过一段时间的研究,我的担忧变成了现实——在 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 control: Clearing cache without clearing cookies 有效)

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

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

【讨论】:

    猜你喜欢
    • 2012-03-01
    • 1970-01-01
    • 2011-11-05
    • 2019-11-04
    • 2016-09-18
    • 1970-01-01
    • 2014-09-22
    • 2011-11-21
    • 1970-01-01
    相关资源
    最近更新 更多