2

My problem is that I created a simple application where I have webrowser control. It navigates every 20 seconds to a new site. After some number of navigations memory occupied by the application increases. I tried to dispose, delete and create again the webrouser control, but couldn't succeed. The only way to release all resources of the application is reboot it. I spent lots of effort trying to solve this problem. Please, give me some hints or links where I can read about it. Thanks in advance.

The actual code is much bigger than the demonstrated one, but the idea is the same. Code looks like this:

for (int i = 0; i < 100000; i++)
{
    webBrowser1.Navigate("http://stackoverflow.com");
    Wait(20000);
}

Method definition:

private void Wait(long value)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();

    while (sw.ElapsedMilliseconds < value)
        Application.DoEvents();
}

Problem is not actual now because the solution is found by using another browser control named WebKitBrowser. Thanks for all who tried to help me. It was my first question on this briliant site. I liked it very much.

Ayaz Alifov
  • 8,334
  • 4
  • 61
  • 56
  • Possible duplicate? http://stackoverflow.com/questions/904478/how-to-fix-the-memory-leak-in-ie-webbrowser-control – Steve Jan 12 '13 at 15:36
  • `memory occupied by the application increases` by what factor? Your code doesn't seem to create a lot of memory, probably errors are in other places – Ilya Ivanov Jan 12 '13 at 15:36
  • Ilya, it does. Just check and you will see that the memory increases significantly. Thank you for the link given. I will try to do the same which is suggested. – Ayaz Alifov Jan 12 '13 at 16:09
  • 1
    Is it an actual _problem_, or do you just see the number go up in Task Manager? – John Saunders Jan 12 '13 at 16:26
  • 2
    Remember that "how much memory my program is using" is a concept that's extremely hard to define in the first place in modern operating systems, especially in a managed program. The .NET runtime might not return memory to the OS and just keep it unused for a while - since the memory use of most programs will fluctuate in a small range, this avoids excessive system calls. You don't have a memory leak when measured memory use doesn't drop as soon as you believe it should; a better indicator is the memory use growing without bounds. – millimoose Jan 12 '13 at 16:43

3 Answers3

1

The problem is still actual. I tried to use a method shown in below link but didn't succeed. How to Fix the Memory Leak in IE WebBrowser Control?

It decreases the memory for a while, then again increases significantly. And so circularly. Here is the modified code:

  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 button1_Click(object sender, EventArgs e)
        {

           for (int i = 0; i < 100000; i++)
              {
                 webBrowser1.Navigate("http://stackoverflow.com");
                 while (webBrowser1.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents();

                // anytime when I want to reduce the occupied memory I do this
                IntPtr pHandle = GetCurrentProcess();
                SetProcessWorkingSetSize(pHandle, -1, -1);
              }
        }



   }
Community
  • 1
  • 1
Ayaz Alifov
  • 8,334
  • 4
  • 61
  • 56
0

You're blocking your main UI thread message loop and using Application.DoEvents, which is evil!

Instead of this, you can use a System.Windows.Forms.Timer like this:

class Form1 : Form
{
  Timer _Timer;
  int _Index = 0;

  public Form1()
  {
    _Timer = new Timer { Enabled = true, Interval = 20000 };
    _Timer.Tick += ( s, e ) => TimerTick();
  }

  void TimerTick()
  {
     if ( _Index >= 100000 )
     {
       _Timer.Dispose();
       _Timer = null;
       return;
     }

     webBrowser.Navigate( ... );

     _Index++;
   }

I'm guessing this will solve your problem. In any case, it's worth doing.

Nick Butler
  • 24,045
  • 4
  • 49
  • 70
  • @JohnSaunders Maybe US / UK English confusion! I've clarified :) – Nick Butler Jan 12 '13 at 16:32
  • Nicholas Butler, thank you for your answer. But what to do if I have: webBrowser1.Navigate("http://stackoverflow.com"); while (webBrowser1.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents(); As can be seen, Application.DoEvents() method is used because we don't know how much time we need to wait to load the page. – Ayaz Alifov Jan 13 '13 at 13:09
  • You can use the [`WebBrowser.DocumentCompleted Event`](http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.documentcompleted.aspx) - here's a question about how to use it correctly: http://stackoverflow.com/questions/2777878/detect-webbrowser-complete-page-loading. What you don't want to do is block the UI message loop, so you can't use `Application.DoEvents` – Nick Butler Jan 13 '13 at 13:21
0

I solved the problem using WebKit Browser. Here is the link for those who are also interested in using it: http://webkitdotnet.sourceforge.net/basics.php?p=4

Ayaz Alifov
  • 8,334
  • 4
  • 61
  • 56