Click here to Skip to main content
15,885,537 members
Please Sign up or sign in to vote.
5.00/5 (2 votes)
See more:
I have a win32 application that loads .net assemblies into a window allowing the user to us it and then close it when they finish.

Problem is my application goes from about 50mb to 200mb when the user opens the .net part and stays there even after the user has closed the hosting window.

I tried disposing of by .net objects and manually garbage collecting but this had little effect. I tried loading the dll through an ApplicationDomain and then un loading it but this seemed worse. I have never used AppDomains before an am a little confused.

Here is the loading code

C#
AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
snapInDomain = AppDomain.CreateDomain(snapInName, null, setup);
Assembly a = snapInDomain.Load(snapInAssembly);


here is the unload code
C#
AppDomain.Unload(snapInDomain);


I was hopeing this was going to give my 150mb back but it just added more memory. Question is: How can I load an assembly (plus dependencies) use it and then unload it and reclaim the memory when I'm finished with it?

Just to add some clarification:

My win32 App accesses a managed .net dll through COM interop - this manged .net dll then loads plugin style .net dlls as required the problem is it keeps the memory that the plugin style dlls occupy even after i've finished with it.

Most examples seem to be based around console style execution, using a domain for my issue seems much more complicated since the plugin which is being loaded is a user control that needs to be hosted on a form in another domain
Posted
Updated 2-Aug-11 23:09pm
v4

Uses a memory profiler to ensure that at least you properly dispose your .NET object.

Memory profiler[^]

Alernatively, you might try a very simple assemblies in which you will allocate 200 objects of 1 KB and then release them (or even no objects at all) and then check your numbers.

200 MB "lost" is quite large...
 
Share this answer
 
Comments
ARopo 29-Jul-11 5:28am    
I think Most of the memory added is the actual size of the dll I'm loading along with all its dependancies. It is not leaking in that it does reach a maximum but since my application is run from a shared server terminal service I need to free up this memory when I'm finised with it.
You need to use AppDomains, and load the DLL in question into the other app domain. You also (obvious in principle but can be hard to remember) need to drop all references to objects in the other assembly to get rid of it. This carries with it other problems like you need to marshal things across the boundary or use MarshalByRefObject proxy classes, but it's the only way to make assemblies unloadable.

I am a bit confused by your question. Are you directly trying to load .Net plugins into an unmanaged process? Or do you have a '.Net part' which is within the main application, and that loads assemblies via the normal .Net mechanism? I have no idea how AppDomains play with unmanaged processes.

There is an example of loading and unloading plugins into an AppDomain in my lobby server and client, and it definitely unloads correctly because you can update the DLL when it is unloaded.
 
Share this answer
 
Comments
ARopo 29-Jul-11 5:21am    
I have c#.Net dll that is available through COM This .Net dll then Loads .net DLLs as shown in the loading code in my question. Problem is that when I unload the application domain it has little of no effect. I Suspect that it is not quite as simple as I first thought.
ARopo 29-Jul-11 5:36am    
I think as you say using AppDomains is the answer, but I'm have difficultly understanding how to set one up, it look as though if I load a dll to a new application domain as in my example it loads the dll to both the new domain and the current domain maybe I need to create a domain and somehow load my dlls from within it.
BobJanova 29-Jul-11 13:29pm    
I think this is the piece of magic you need (from my lobby server):

public static PluginLoader Make(PluginInfo pi){
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationName = "Plugins";
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
pi.domain = AppDomain.CreateDomain("plugin", null, setup);
pi.domain.DomainUnload += new EventHandler(DomainUnload);
PluginLoader loader = (PluginLoader)pi.domain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, "RedCorona.GameServer.PluginLoader");
return loader;
}

That ensures that the instance gets created in the domain you just created, and therefore it can be unloaded.

Using Activator.CreateInstance on types retrieved from the assembly, I think, means they get instantiated in the main AppDomain and therefore can't be uploaded.
Asish Limbu 3-Aug-11 5:35am    
Good Explanation.+5.
I'm going to try this

http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/a6a896ca-8905-41fb-8f52-7f39e89c9a91/[^]

Most examples seem to be around console style execution, using a domain for my issue seems much more complicated since the plugin which is being loaded is a user control that needs to be hosted on a form in another domain

Thanks to everyone for their contribution. The biggest problem I had was understanding domains, as it turns out I would need to redesign our plugin mechanism significantly to put my plugins in their own domains. The interface between the host and the plugin is a usercontrol/embedded in a VB6 form as an activeX so is not easy to separate out. However I managed to fix a significant memory issue as follows:

In the VB6 Form a .net user control is created using:
VB
Set EntryControl = Me.Controls.Add(ctlname, "Entry")


In the form unload the release is called by setting entrycontrol to nothing:
VB
Set EntryControl = Nothing


The problem was I also had some reference to interfaces of EntryControl, once these where set to nothing the com interface is released and garbage collection can occur

VB
Set iEntryControlInterface1 = Nothing
Set iEntryControlInterface2 = Nothing
Set EntryControl = Nothing
 
Share this answer
 
v4
Did you tried this ? http://msdn.microsoft.com/en-us/library/dd380850.aspx[^]

Or you just have a managed C++ library ?
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900