dll file is getting locked even after the domain in which it is loaded is unloaded
hi,
i am having a problem with dyanmic loading of assemblies.the problem is that the dll file is getting locked even after the domain in which it is loaded is unloaded.The code below shows a dll search being loaded in domain appdomain.then we get a specific type from the dll and unload the domain thereafter.
Now if we want to replace the search dll or delete it ,it is shown as being used and hence can't be deleted.
But unloading a domain should have made it free.Does anyone have a solution for this behaviour .please help.code is as follows
===============================
AppDomain appdomain = AppDomain.CreateDomain("loader domain");
Type t =appdomain.Load(@"Search").GetType("Search.Component");
AppDomain.Unload(appdomain);
===============================================
i could have used shadow property but then i am unloading the domain hosting it so there should be no reference to it in the memory
regards,
ramneek
[1003 byte] By [
ramneek] at [2008-2-15]
Hi Ramneek,
The problem you're having is that you're actually loading the assembly in both your "loader domain", and the domain in which the code you show is running. Your call to appdomain.Load(@"Search") returns an instance of an Assembly class. However, Assembly is not a MarshalByRefObject. This means that an instance of the Assembly class (rather than a reference to the Assembly object loaded in the loader domain) needs to exist in the domain that calls AppDomain::Load.
In order to prevent the Assembly from being loaded in both domains, I recommend creating an intermediate class, which you load into the new domain. That class would then do the work of loading the Assembly. For instance:
| |
internal class AssemblyLoader : MarshalByRefObject { public void WorkWithType(string assemblyName, string typeName) { Assembly.Load(assemblyName).GetType(typeName); } }
|
Then in place of the code you have now:
| |
AppDomain appdomain = AppDomain.CreateDomain("loader domain"); AssemblyLoader loader = appdomain.CreateInstanceAndUnwrap(typeof(AssemblyLoader).Assembly.GetName().FullName, typeof(AssemblyLoader).FullName) as AssemblyLoader; loader.WorkWithType(@"Search", @"Search.Component"); AppDomain.Unload(appdomain);
|
Ok, I tried doing just what you said, and I'm seeing the oddest thing happen. Before unloading the sandbox AppDomain, the assembly I'm loading only shows up in that AppDomain and not the primary one (this is found by simply checking AppDomain.GetAssemblies()). But after I unload the sandbox, the assembly shows up in my primary AppDomain (!). My only guess is that one of the object references I have is causing this to happen, but if that's the case, I don't know how to prevent it.
| | AppDomain sandbox = AppDomain.CreateDomain("Capability Load Sandbox"); AssemblyLoader al = (AssemblyLoader) sandbox.CreateInstanceAndUnwrap("ConsoleTestApp", typeof(AssemblyLoader).FullName); al.WorkWithAssembly(name.FullName); al = null;DisplayAssembliesInDomain(AppDomain.CurrentDomain); DisplayAssembliesInDomain(sandbox); Console.WriteLine("Unloading the sandbox.\n");
AppDomain.Unload(sandbox); DisplayAssembliesInDomain(AppDomain.CurrentDomain);
|
For convenience, I'll throw in the other code, though it's not interesting:
| |
private static void DisplayAssembliesInDomain(AppDomain sandbox) { Console.WriteLine("Loaded assemblies in {0}:", sandbox.FriendlyName); foreach (Assembly a in sandbox.GetAssemblies()) { Console.WriteLine(a.FullName); }
Console.WriteLine(); } internal class AssemblyLoader : MarshalByRefObject { public void WorkWithAssembly(string assemblyName) { Assembly a = Assembly.Load(assemblyName); a = null; } }
|