I know this is a hot discussed topic with many questions and answers but I still do not find the solution for the following problem:
I have a multi-tab application. On every tab is a Webbrowser control.
As the webbrowsers take more an more memory for every new tab and they do not free this memory on tab-close, I decided to make a Webbrowser.Dispose() in the tab close event handler. This helped me concerning the memory leak. all the used RAM is now free after closing.
But this caused a new problem: After the first Dispose() it seems that the session is destroyed for all other Webbrowser objects.
Normally I only login in to the frist webbrowser. If I a add several tabs I am normally logged in automatically. After the first Dispose() this does not work anymore and I have to login on every new Tab.
I tried to keep the old cookies and send them again with the new webbrowser but this did not solve the problem. The seems to be destroyed.
This seems to be a GarbageCollector-Problem. You can try to use the dirty way of System.GC.Collect(), just calling the GarbageCollector to free memory, but this is not a good way to solve the problem.
Of what you told, this seems to be a Pointer-problem.
If you declared the Connection as a global variable, you have to detach the connection from the tab befor you can close/dispose the tab itselve. The event Me.Closing shuld help you to do so.
If the Pointer stays open, the tab as an object is still connected on the Connection and will (not realy shure if/when) not get cleaned by the GC.
If you can clarify your way of duplicating/referencing the connection, I could give a more detailed answer.
EDIT: after a while of research my worries became true - there is a problem with caching under IE (>5 as far as I know). http://social.msdn.microsoft.com/Forums/ie/en-US/88c21427-e765-46e8-833d-6021ef79e0c8/memory-leak-in-ie-webbrowser-control
Suggestions are:
calling GarbageCollector manually
limit MemUsage (can result in application-crashes and also just writes the pages to disk)
about:blanc to override cache-entries
calling C++ methods to override the cache (WinINet - all I have found resulted in some ProtectedMemory-Errors - maybe this C# WebBrowser control: Clearing cache without clearing cookies works)
using C++ and WinINet (I don't know any real .Net implementation and it may also have this memory leak)
using alternatives to IE like gecko (Mozilla) - https://bitbucket.org/geckofx/
All WebBrowser instances share the session on per-process basis. According to EricLaw's answer to a similar question, it appears to be impossible to separate sessions. I'd trust Eric's statement as he worked as IE program manager at Microsoft.
If however you'd still like to try some hacks, you may look at CoInternetGetSession. First, try saving and holding on to the returned reference to IInternetSession. Further, you could look at registering your own URL namespace (RegisterNameSpace) and implementing a pluggable protocol handler which may eventually allow to overrule this restriction.
Of course, it sounds like an overkill and most likely won't help at all. A clean solution might be to redesign the logic to get rid of cookies and pass the state via URLs.
EDITED: Another idea, try to navigate the WebBrowser instance to (say) "about:blank" and wait for DocumentComplete event, before actually disposing of it with Dispose().
Thanks for your answers. Here what I checked out:
Calling GC manually:
-
Does only help if I use Webbrowser.Dispose() in before.
But this is not a solution because of the session problem.
Limit Mem Usage:
- Not a solution. This program should run a whole day with many opening and closing of tabs. If I can not clean the used memory, the memory usage will be too much after some hours..
about:blank:
- I called about:blank on Closing the Tab. After DocumentLoaded occurs for this URL I disposed the Webbrowser. Same procedure as calling Dispose directly. Session breaks down.
Other components:
- I need to have an IE control in every case because the (proprietary) internet application only supports IE 8 and higher.
"Using c++ and WinInet":
- Can I use the C++ Browser in my .net program? I can not switch the whole program to C++. This wouldn't be a solution for me.
In summary:
My application works fine without Dispose but has the problem with the increasing memory usage. If we could find a solution for this (which seems to be impossible) it would be the best solution.
The only thing what would be an acceptable "workaround" for me is to reuse the "closed" webbrowsers. In detail: On every tab close I add the Webbrowser to a List instead of Dispose them. When I need a new tab I take the first out of the list an reuse it and Navigate to the new URL: I tried it out but it seems there is the same problem with the sessions. The sessions in the reused tabs seems to be new again. But I really do not understand why... An suggestions for this, too?
Another workaround would be to force every Webbrowser object to be a single instance. Is this possible?