Контрол WebBrowser и проблемы с памятью (c# webbrowser memory leak)

21 января 2017,

Кто работает с контролом WebBrowser в C#/VB знают, что он большой любитель отъедать память огромными кусками и, в следствии этого, замертво падать. В интернетах на эту тему много обсуждений. Кому-то помогает один вариант, кому-то другой. Мне не помогал ни один вариант, пока одним субботним вечером я не решил применить к этому контролу старый как мир метод Dispose(). Совсем "неожиданно" контрол вернул часть съеденной памяти, но, правда, и был лишён дальнейшей работы с ним, так как GC его быстренько зачистил. Немного пошаманив родилась простая, как слеза младенца, конструкция, благодаря которой можно было не проверять каждые полчаса не упало ли приложение из-за OutOfMemoryException. Спешу поделиться ею с такими же горемыками, штудирующими несчётное количество страниц на StackOverflow и MSDN.



public partial class Form1 : Form
    {
        [DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
        internal static extern bool SetProcessWorkingSetSize(IntPtr pProcess, int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);

        [DllImport("KERNEL32.DLL", EntryPoint = "GetCurrentProcess", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
        internal static extern IntPtr GetCurrentProcess();

        private void ReNewBrowser()
        {
            webBrowser1.Dispose();
            webBrowser1 = null;

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

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            webBrowser1 = new WebBrowser();

            //Это уже мои заморочки, но на всякий случай не забудьте про них
            webBrowser1.Location = new Point(11, 42);
            webBrowser1.Size = new Size(1054, 659);
            webBrowser1.ScriptErrorsSuppressed = true;

            webBrowser1.DocumentCompleted += webBrowser1_DocumentCompleted;
            webBrowser1.Navigating += webBrowser1_Navigating;

            splitContainer1.Panel1.Controls.Add(webBrowser1);
            // конец заморочек

            webBrowser1.Show();
        }
    }