Как исправить утечку памяти в элементе управления IE WebBrowser? - PullRequest
29 голосов
/ 24 мая 2009

Я пытаюсь встроить элемент управления WebBrowser в приложение C # Winform. Это звучит достаточно просто. Однако я обнаружил, что элемент управления WebBrowser поглощает много памяти каждый раз, когда я вызываю метод Navigate. Память никогда не освобождается. Использование памяти растет и растет…

У многих людей в сети точно такая же проблема, но я пока не нашел удовлетворительного ответа. Это лучшее обсуждение этой проблемы, которое я нашел до сих пор:

Утечка памяти в IE WebBrowser Control

Один человек предложил обновить до IE8, чтобы исправить проблему.

Однако мне нужно решение, которое работает независимо от того, установлена ​​ли у пользователя последняя версия IE. У меня нет контроля над пользовательской средой.

Кто-нибудь знает, как освободить память, занятую элементом управления WebBrowser? Есть ли обходные пути? Существуют ли альтернативы элементу управления WebBrowser?

Обновление: Я только что сделал еще несколько тестов. На работе я использую Windows XP и IE6. Память там не растет. Память увеличивается при вызове метода навигации, но освобождается через некоторое время. Дома я использую Vista и обновился до IE8. Здесь я тоже не вижу проблемы больше. Похоже, что проблема специфична для IE7. Поэтому вопрос следует перефразировать так: «Как исправить утечку памяти в IE WebBrowser Control, когда установлен IE7». Кто-нибудь может подтвердить, что эта проблема специфична для IE7?

Ответы [ 18 ]

0 голосов
/ 17 июня 2015

У меня были такие же похожие проблемы. Я отправил более 5000 запросов навигации через веб-браузер, чтобы очистить динамические страницы. Приблизительно после 50 запросов у меня не хватило бы памяти, так как после каждого запроса не использовалось использование памяти для запроса навигации Я использовал webBrowser.Dispose () после навигации, и это решило проблему. Это не связано с IE7 или около того. Я использую IE 11 и получил ту же проблему. Это потому, что я не выбрасывал навигационные объекты. Надеюсь, это поможет.

0 голосов
/ 09 мая 2013

Я думаю, что этот вопрос давно остался без ответа. Столько тем с одинаковым вопросом, но не окончательным ответом.

Я нашел способ обойти эту проблему и хотел бы поделиться со всеми вами, кто все еще сталкивается с этой проблемой.

step1: создайте новую форму, скажем form2, и добавьте в нее элемент управления веб-браузера. Шаг 2: В форме 1, где у вас есть элемент управления веб-браузера, просто удалите его. Шаг 3: Теперь перейдите к Form2 и сделайте модификатор доступа для этого элемента управления веб-браузера общедоступным, чтобы к нему можно было получить доступ в Form1. Шаг 4. Создайте панель в form1 и создайте объект form2 и добавьте его в панель. Form2 frm = новая Form2 (); frm.TopLevel = false; frm.Show (); panel1.Controls.Add (FRM); шаг 5: вызывать приведенный ниже код через равные промежутки времени frm.Controls.Remove (frm.webBrowser1); frm.Dispose ();

Вот и все. Теперь, когда вы запустите его, вы увидите, что элемент управления веб-браузера загружен, и он будет регулярно удаляться, и приложение больше не будет зависать.

Вы можете добавить приведенный ниже код, чтобы сделать его более эффективным.

    IntPtr pHandle = GetCurrentProcess();
    SetProcessWorkingSetSize(pHandle, -1, -1);


    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
0 голосов
/ 22 июня 2012

Вставьте следующий код после загрузки страницы

System.Diagnostics.Process loProcess = System.Diagnostics.Process.GetCurrentProcess();
try
{
     loProcess.MaxWorkingSet = (IntPtr)((int)loProcess.MaxWorkingSet - 1);
     loProcess.MinWorkingSet = (IntPtr)((int)loProcess.MinWorkingSet - 1);
}
catch (System.Exception)
{
     loProcess.MaxWorkingSet = (IntPtr)((int)1413120);
     loProcess.MinWorkingSet = (IntPtr)((int)204800);
}
0 голосов
/ 21 февраля 2012

Я просмотрел весь интернет и не смог найти ответ на эту проблему. Я исправил это, используя ниже:

Protected Sub disposeBrowers()
    If debug Then debugTrace()
    If Me.InvokeRequired Then
        Me.Invoke(New simple(AddressOf disposeBrowers))
    Else
        Dim webCliffNavigate As String = webCliff.Url.AbsoluteUri

        'Dim webdollarNavigate As String = webDollar.Url.AbsoluteUri
        Me.splContainerMain.SuspendLayout()
        Me.splCliffDwellers.Panel2.Controls.Remove(webCliff)
        Me.splDollars.Panel2.Controls.Remove(webDollar)
        RemoveHandler webCliff.DocumentCompleted, AddressOf webCliff_DocumentCompleted
        RemoveHandler webDollar.DocumentCompleted, AddressOf webDollar_DocumentCompleted
        RemoveHandler webCliff.GotFocus, AddressOf setDisposeEvent
        RemoveHandler webCliff.LostFocus, AddressOf setDisposeEvent
        RemoveHandler webDollar.GotFocus, AddressOf setDisposeEvent
        RemoveHandler webDollar.LostFocus, AddressOf setDisposeEvent
        webCliff.Stop()
        webDollar.Stop()

        Dim tmpWeb As SHDocVw.WebBrowser = webCliff.ActiveXInstance
        System.Runtime.InteropServices.Marshal.ReleaseComObject(tmpWeb)
        webCliff.Dispose()

        tmpWeb = webDollar.ActiveXInstance
        System.Runtime.InteropServices.Marshal.ReleaseComObject(tmpWeb)
        webDollar.Dispose()

        webCliff = Nothing
        webDollar = Nothing
        GC.AddMemoryPressure(50000)
        GC.Collect()
        GC.WaitForPendingFinalizers()
        GC.Collect()
        GC.WaitForFullGCComplete()
        GC.Collect()
        GC.RemoveMemoryPressure(50000)
        webCliff = New WebBrowser()
        webDollar = New WebBrowser()
        webCliff.CausesValidation = False
        webCliff.Dock = DockStyle.Fill
        webDollar.CausesValidation = webCliff.CausesValidation
        webDollar.Dock = webCliff.Dock
        webDollar.ScriptErrorsSuppressed = True
        webDollar.Visible = True
        webCliff.Visible = True
        Me.splCliffDwellers.Panel2.Controls.Add(webCliff)
        Me.splDollars.Panel2.Controls.Add(webDollar)
        Me.splContainerMain.ResumeLayout()

        'vb.net for some reason automatically recreates these and the below is not needed
        'AddHandler webCliff.DocumentCompleted, AddressOf webCliff_DocumentCompleted
        'AddHandler webDollar.DocumentCompleted, AddressOf webDollar_DocumentCompleted
        'AddHandler webCliff.GotFocus, AddressOf setDisposeEvent
        'AddHandler webCliff.LostFocus, AddressOf setDisposeEvent
        'AddHandler webDollar.GotFocus, AddressOf setDisposeEvent
        'AddHandler webDollar.LostFocus, AddressOf setDisposeEvent

        webCliff.Navigate(webCliffNavigate)
        'webDollar.Navigate(webdollarNavigate)
        disposeOfBrowsers = Now.AddMinutes(20)
    End If
End Sub

Я знаю, что это не самое красивое или идеальное решение, но оно мне очень помогло. - Лейла

0 голосов
/ 23 июня 2009

Я столкнулся с той же проблемой, но вместо того, чтобы перейти на новую страницу, я просто переписал ту же HTML-страницу, используя объект system.oi.streamreader / writer, и вызвал обновление. Очевидно, что это не сработает в ситуации, когда контент для браузера подается онлайн, но мне это удается.

Кроме того, в настоящее время я использую более 8 элементов управления браузером, которые все активны одновременно, для предоставления отчетов через javascript в моем приложении .net. Когда пользователь активирует один браузер, html, на который указывают другие браузеры, очищается, а браузеры обновляются. Используя 8 браузеров, работающих с этими двумя методами, я могу легко держать свое приложение под управлением памяти Firefox, открыв всего 3 вкладки.

0 голосов
/ 28 апреля 2018

Просто объявите элемент управления WebBrowser, используя ключевое слово «using». Это прекратит утечку памяти при вызове метода Navigate () больше. Я только что проверил это, и он работал хорошо для меня.

using (var webBrowser = new System.Windows.Forms.WebBrowser())
{
    webBrowser.Navigate(url);
}
0 голосов
/ 19 июня 2018

Я столкнулся с этой проблемой при простом веб-браузере в форме. Он перешел на одну веб-страницу и остался там. По словам диспетчера задач, в течение 10 минут он израсходовал 2 ГБ памяти из 120 МБ.

Простым решением для моего проекта было перейти к свойствам элементов управления веб-браузера в Visual Studio и изменить значение «AllowNavigation» на false. Теперь, когда я запускаю свою программу, она остается на 120 МБ. Надеюсь, это кому-нибудь поможет!

0 голосов
/ 24 мая 2009

Я использую веб-элемент управления в приложении, но поскольку мое приложение перемещается только на одну страницу, я не заметил проблему, о которой вы упомянули. Есть еще один веб-элемент управления, который на самом деле является оберткой, и я не знаю, есть ли у него такая же проблема или нет. Вы можете найти его здесь .

...