开发者

Load DLL create Instance and Unload

I have a Application which copies a DLL (UserControlLibrary) to its own Debug/Release folder and loads it using this Code:

AppDomain appDomain = AppDomain.CreateDomain("MyDomain");
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "DLLs (*.dll)|*.dll";
if (dialog.ShowDialog().Value)
{
    string newLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\" + dialog.SafeFileName;
    File.Copy(dialog.FileName, newLocation, true);
    Assembly assembly = appDomain.Load(AssemblyName.GetAssemblyName(newLocation));
    UserControl userControl = (UserControl) assembly.CreateInstance("WpfControlLibrary1.UserControl1");
}

I now add that UserControl to a Grid using:

grid.Children.Add(userControl);

Works fine. Now I try to unload the DLL using:

AppDomain.Unload(appDomain);
grid.Children.Clear();

If I now try to load the DLL (because it changed meanwhile) again using the above code I get an error telling me the file is in use (File.Copy).

I've read a lot of things and my guess is that I'm not allowed to use the UserControl like I did (because that loads into the Main AppDomain). How do I have to change the Code to make it work?

I've also read a lot of things about using MarshalByRefObject but unfortunately I was unable to implement it in this project. A example or modification of the code above would be nice.

EDIT:

From the comments I've read so far (es开发者_Go百科pecially from svick) it looks like I have to use "AppDomain.CreateInstanceAndUnwrap" instead of "AppDomain.Load". I've seen that approach already while searching for a solution earlier but as svick mentioned that doesn't work because a UserControl can't inherit from MarshalByRefObject.

Does anyone know another way?


Read the documentation for AppDomain.Load(). It specifically says that this method loads the assembly both into the assembly you are calling the method on and into the current assembly. So, even when you unload the app domain, the assembly still stays loaded in the current assembly.

I'm not sure there is a way around this as you can't make UserControl inherit from MarhshalByRefObject.


When you call unload, the AppDomain is not immediately unloaded (see MSDN for the full article):

When a thread calls Unload, the target domain is marked for unloading. The dedicated thread attempts to unload the domain, and all threads in the domain are aborted. If a thread does not abort, for example because it is executing unmanaged code, or because it is executing a finally block, then after a period of time a CannotUnloadAppDomainException is thrown...


Perhaps this quote from the MSDN article for AppDomain.Unload could explain things:

In the .NET Framework version 2.0 there is a thread dedicated to unloading application domains. This improves reliability, especially when the .NET Framework is hosted. When a thread calls Unload, the target domain is marked for unloading. The dedicated thread attempts to unload the domain, and all threads in the domain are aborted. If a thread does not abort, for example because it is executing unmanaged code, or because it is executing a finally block, then after a period of time a CannotUnloadAppDomainException is thrown in the thread that originally called Unload. If the thread that could not be aborted eventually ends, the target domain is not unloaded. Thus, in the .NET Framework version 2.0 domain is not guaranteed to unload, because it might not be possible to terminate executing threads.

Maybe there are some rogue threads that are keeping the app domain alive and therefore also keeping your file locked.

As a workaround, you could copy the DLLs to random file names instead.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜