我有一个.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。如果在我离开谷歌后将释放内存,这将不会成为问题。但事实并非如此。
我也试过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即时,然后按startButton
(调用startButton_Click
)。大约80页后,我按stopButton
,然后导航到“about:blank”,然后返回Google并搜索其他内容,再次按startButton
。
我首先在我的PC上测试了这个,它有6 GB内存。当我达到1.5 GB时,应用程序停止响应,但我没有得到任何OutOfMemory
异常。然后我在Windows 7和1 GB RAM的虚拟机上测试了它。当它达到大约300 MB时,我的应用程序中的Web浏览器没有响应。
如果我按下调出freeMem
的{{1}}按钮,内存会恢复原状(但请参阅我的Edit2)。这样就“解决了”我的问题。但现在我的问题是为什么我需要拨打freeMemButton_Click
?是不是Windows应该自动释放内存?此外,我不确定调用该函数是否会产生任何副作用。
我很确定这是一个错误。我应该继续报告吗?
Edit2:我测试了Stefan的解决方案(调用SetProcessWorkingSetSize
)并没有修复它。内存在任务管理器上失败,但这只是显而易见的。在没有调用该功能的情况下,在多次浏览器导航变得无响应之后,应用程序变得没有响应。
答案 0 :(得分:3)
如果没有原因,Windows并不真正返回释放的内存。唯一的原因是,如果另一个应用程序需要内存,并且没有其他内存可用了。这就是看起来内存使用量增加的原因。
尝试拨打
SetProcessWorkingSetSize(GetCurrentProcess(), - 1,-1);
有时 - 这会强制操作系统将所有释放的内存返回给操作系统。
答案 1 :(得分:0)
我认为HtmlElement pnext没有发布,因为它是ComObject,并且浏览器控件中可能存在错误。
尝试pnext.Release或尝试使用Marshal.Release并获取要释放的ComObject实例。
答案 2 :(得分:0)
在使用Webbrowser时,我发现等待“documentcompleted”事件并检查“状态”是否“已完成”并且导航没有下一页是很重要的。否则取消导航并再次等待文档完成状态(中止)bevore导航....
可能是使用定时器而不检查Webbrowser的状态可能是个问题
Webbrowser-Control的下一步是,你不能在多线程/背景工作中使用它,因为它需要是STA ....(通常会导致应用程序无响应)
使用.NET的“ful-contol”(解析网站)的解决方案是使用WebRequest / Webresponse,如果你想让DOM“自动”,你可以再次将结果转换为Webbroswer.Document执行,使用多线程,轻松设置超时/代理,我发现比使用Web浏览器控件更舒服。
尽管如此,我成功地使用此处的提示(How to Fix the Memory Leak in IE WebBrowser Control?)
在另一个项目中实现了Webbrowser-Control解析页面 使用Winforms编程的另一个“搞笑”瘦身我发现,当窗口最小化时再次打开时,似乎触发了GC.Collect - &gt;这会降低内存使用量吗? (也许Stefan的帖子也引用了这个问题)