У меня есть приложение .NET, которому нужно использовать WebBrowser
для автоматической навигации по множеству страниц.Но если я зайду, например, в Google и включу Google Instant, а затем выполню поиск чего-либо и несколько раз вручную перейду к следующей кнопке, объем памяти, используемой моим приложением, начнет увеличиваться.
Возможно, проблема заключается в следующем.что 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
Итак, как вы можете видеть, память увеличивается почти линейнона 30 - 35 МБ каждые 10 страниц.Это не будет проблемой, если память будет освобождена после того, как я уйду из Google.Но это не так.
Я также пытался это и ничего не делал.
Редактировать: Я создал проект только для проверки этого.Вот мой 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 с Google Instant, включившим на , а затем нажмите startButton
(который вызывает startButton_Click
).Приблизительно после 80 страниц я нажимаю stopButton
, затем перехожу к «about: blank», затем возвращаюсь к Google и ищу что-нибудь еще и снова нажимаю startButton
.
Сначала я проверил это на своем ПК с оперативной памятью 6 ГБ.Когда я достиг 1,5 ГБ, приложение перестало отвечать, но я не получил исключение OutOfMemory
.Затем я проверил его на виртуальной машине с Windows 7 и 1 ГБ оперативной памяти.Когда он достиг примерно 300 МБ, веб-браузер в моем приложении перестал отвечать на запросы.
Если я нажму кнопку freeMem
, которая вызывает freeMemButton_Click
, память снова откроется (но см. Мой Edit2).Так что это "решает" мою проблему.Но теперь мой вопрос: зачем мне звонить SetProcessWorkingSetSize
?Разве Windows не должна автоматически освобождать память?Кроме того, я не уверен, что вызов этой функции будет иметь какой-либо побочный эффект.
Я уверен, что это ошибка.Должен ли я пойти дальше и сообщить об этом?
Edit2: Я проверил решение Стефана (вызов SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1)
) и не исправил его.Память у менеджера задач опустилась, но это только очевидно.Приложение перестало отвечать на запросы после того, как многие браузеры перестали отвечать на запросы, когда не вызывали эту функцию.