Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
503 views
in Technique[技术] by (71.8m points)

c# - Help needed with unloading .DLL's from AppDomain - Still not working even with ShadowCopy

I am trying to do the following. App A is the "mother app". It stays open. App B is just a .DLL where I write some classes that are derived from an interface specified in App A.

Then, from App A, I will "import" classes from App B and run methods within them. I want to be able to dynamically change App B (change code and recompile) and use the new code in App A.

I have a post-compile command in App B that copies the new .DLL to the App A directory. App A creates a new AppDomain and uses ShadowCopying. I thought this would be sufficient, but when I try to recompile & copy App B's new .DLL, it says that the file is in use and can't be overwritten.

Here is the code I have as of now:

App A (TestServer in code):

namespace TestServer
{
    public interface IRunnable
    {
        void Run();        
    }

    class Program
    {        
        static void Main(string[] args)
        {
            AppDomainSetup setup = new AppDomainSetup();
            setup.ApplicationName = "DemoApp";
            setup.ApplicationBase = Environment.CurrentDirectory;
            setup.ShadowCopyDirectories = Environment.CurrentDirectory;
            setup.ShadowCopyFiles = "true";
            int _domain = 1;

            while (true)
            {
                string typeName = Console.ReadLine();

            AppDomain appDomain = AppDomain.CreateDomain("DemoDomain" + _domain, null, setup);

            IRunnable runner = appDomain.CreateInstanceFromAndUnwrap("TestClient.dll", typeName) as IRunnable;

            runner.Run();

            AppDomain.Unload(appDomain);
            _domain++;
            }
        }   
    }   
}

App B (TestClient in code):

namespace TestClient
{    
    public class TestRunner : TestServer.IRunnable
    {
        public void Run()
        {
            Console.WriteLine("RUNNING");
        }
    }

    public class Bob : TestServer.IRunnable
    {
        public void Run()
        {
            Console.WriteLine("BOB");
        }
    }
}

I have read that if you use stuff from other app domains, those app domains could automatically load the .DLL or something along those lines. In this case, I fear that using the Interface is causing the base AppDomain to load the .DLL thereby locking it up.

How can I resolve this issue / is there a better setup??

NOTE: I have update my code and it still yields the same result.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your code still runs in the mother AppDomain, as you're pulling in assemblies and types into there. Any code should run in the spawned domain. I've shown one way to set something like that up on my website : A simple way to start your code in a different AppDomain

I'm not 100% sure on that but that's certainly one step you'll have to undertake

Update

In terms of the solution presented there, your instantiation of a runner would happen in an inheritor of DomainLifetimeHook. The infrastructure shown ensures that the Start and Stop methods run in the AppDomain created by the class AppDomainExpander. That Expander is the class that creates the new domain, hence your domain setup should go in the Create method of the domain.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...