【问题标题】:WebBrowser memory problem浏览器内存问题
【发布时间】:2011-09-03 03:00:15
【问题描述】:

我有一个 .NET 应用程序,它需要使用 WebBrowser 来自动浏览一堆页面。但是,如果我去,例如,谷歌并设置谷歌即时,然后搜索任何东西并通过下一个按钮手动导航几次,我的应用程序使用的内存将开始增加。

问题可能是 Google Instant 以某种方式保留了以前页面的数据,但即使在我导航到其他地方(例如“about:blank”)后,所使用的内存也不会减少。 IE 9 也会出现这个问题。我开始写下我在第 60 页使用的内存,这就是我得到的(使用 IE 9):

Page 60: 180 MB
Page 70: 214 MB
Page 80: 245 MB
Page 90: 280 MB

如您所见,内存每 10 页几乎线性增加 30 - 35 MB。如果在我离开 Google 后释放内存,这将不是问题。但不是。

我也试过this,但什么也没做。

编辑:我做了一个项目只是为了测试这个。这是我的Form1 代码:

namespace WebBrowserMemoryTest
{
    public partial class Form1 : Form
    {
        private int _Pages;

        public Form1()
        {
            InitializeComponent();
            webBrowser1.Navigate("http://www.google.com");
        }

        private void startButton_Click(object sender, EventArgs e)
        {
            _Pages = 0;
            timer1.Start();
        }

        private void stopButton_Click(object sender, EventArgs e)
        {
            timer1.Stop();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            HtmlElement next = webBrowser1.Document.GetElementById("pnnext");

            if (_Pages <= 90)
            {
                if (null != next)
                {
                    string href = next.GetAttribute("href");
                    webBrowser1.Navigate(href);
                    _Pages++;
                }
                else
                {
                    timer1.Stop();
                    MessageBox.Show("Next button not found");
                }
            }
            else
            {
                timer1.Stop();
                MessageBox.Show("Done");
            }
        }

        private void goButton_Click(object sender, EventArgs e)
        {
            webBrowser1.Navigate(textBox1.Text);
        }

        private void freeMemButton_Click(object sender, EventArgs e)
        {
            MemoryManagement.FlushMemory();
        }
    }

    public class MemoryManagement
    {
        [DllImport("kernel32.dll")]
        public static extern bool SetProcessWorkingSetSize(IntPtr proc, int min, int max);

        public static void FlushMemory()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
            }
        }
    }
}

我所做的是在开启 Google Instant 的情况下在Google 中搜索任何内容,然后按startButton(调用startButton_Click)。大约 80 页后,我按下 stopButton,然后导航到“about:blank”,然后返回 Google 并搜索其他任何内容,然后再次按下 startButton

我首先在具有 6 GB 内存的 PC 上进行了测试。当我达到 1.5 GB 时,应用程序停止响应,但我没有收到任何 OutOfMemory 异常。然后我在具有 Windows 7 和 1 GB 内存的虚拟机上对其进行了测试。当它达到大约 300 MB 时,我的应用程序中的网络浏览器变得无响应。

如果我按下调用freeMemButton_ClickfreeMem 按钮,则内存会回落(但请参阅我的Edit2)。这样就“解决”了我的问题。但现在我的问题是为什么我需要打电话给SetProcessWorkingSetSize? Windows不应该自动释放内存吗?另外,我不确定调用该函数是否会产生任何副作用。

我很确定这是一个错误。我应该继续举报吗?

Edit2:我测试了 Stefan 的解决方案(调用 SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1))并没有修复它。内存在任务管理器上下降,但这只是明显的。在不调用该函数时,应用程序在浏览器导航多次后变得无响应。

【问题讨论】:

  • 您是否在网络浏览器上附加了任何事件处理程序?

标签: .net webbrowser-control


【解决方案1】:

如果没有理由,Windows 不会真正返回释放的内存。唯一的原因是如果另一个应用程序需要该内存并且不再有其他可用内存。这就是为什么看起来内存使用量增加了。

尝试调用

SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1);

有时 - 这会强制操作系统将所有释放的内存返回给操作系统。

【讨论】:

  • 在 Windows 不释放内存的情况下达到 1.5 GB 是否正常?
  • 我进行了测试。那不能解决问题。内存似乎确实在任务管理器上释放了,但是在不调用该函数时,应用程序在浏览器导航相同数量的浏览器后变得无响应。
【解决方案2】:

我认为 HtmlElement pnext 没有发布,因为它是 ComObject,并且浏览器控件中可能存在错误。

尝试 pnext.Release 或尝试 Marshal.Release 并获取 ComObject 的实例以释放。

【讨论】:

  • 刚刚尝试将if(null != next) Marshal.ReleaseComObject(next.DomElement); 行添加到我的timer1_Tick 方法的末尾,但没有任何区别。已达到 1 GB。
  • 导航前请尝试调用 MemoryManagement.FlushMemory
【解决方案3】:

在使用 Webbrowser 时,我发现等待“documentcompleted”事件并检查“状态”是否为“已完成”非常重要,以免导航到下一页。否则取消导航并在导航之前再次等待文档完成状态(中止)......

可能是使用计时器而不检查网络浏览器的状态可能是个问题

Webbrowser-Control 的下一个问题是,您不能在多线程/Backgroundworker 中使用它,因为它需要是 STA....(通常会导致应用程序无响应的问题)

对我来说,使用 .NET 的“ful-contol”(解析网站)的解决方案是使用 WebRequest / Webresponse ,如果您希望 DOM 为“自动”,您可以再次将结果转换为 Webbroswer.Document执行,使用它多线程,轻松设置超时/代理,我发现这比使用 Webbrowser-control 更舒服。

尽管如此,我使用此处的提示 (How to Fix the Memory Leak in IE WebBrowser Control?) 成功地在另一个项目中实现了 Webbrowser-Control 解析页面

我发现的另一个“有趣”的 Winforms 编程瘦身是,当窗口最小化并再次打开时似乎触发了 GC.Collect -> 这会减少内存使用吗? (也许 Stefan 的帖子也提到了这个问题)

【讨论】:

  • 不幸的是,我尝试了所有这些(链接中的解决方案,最小化应用程序)但没有任何效果。我什至尝试删除 TravelLog 条目,但无济于事。
猜你喜欢
  • 1970-01-01
  • 2015-08-05
  • 2015-09-06
  • 2011-10-14
  • 2011-08-18
  • 1970-01-01
  • 2011-01-13
  • 1970-01-01
相关资源
最近更新 更多