【问题标题】:How do I create an application domain and run my application in it?如何创建应用程序域并在其中运行我的应用程序?
【发布时间】:2011-02-08 13:21:44
【问题描述】:

我需要创建一个自定义应用程序域来解决 .NET 运行时 default behavior 中的错误。我在网上看到的示例代码都没有帮助,因为我不知道将它放在哪里,或者它需要在我的 Main() 方法中替换什么。

【问题讨论】:

    标签: c# appdomain


    【解决方案1】:

    可能应该注意的是,创建AppDomains 只是为了解决可以用常量字符串修复的问题,这可能是错误的做法。如果您尝试做与您记下的链接相同的事情,您可以这样做:

    var configFile = Assembly.GetExecutingAssembly().Location + ".config";
    if (!File.Exists(configFile))
        throw new Exception("do your worst!");
    

    递归入口点 :o)

    static void Main(string[] args)
    {
        if (AppDomain.CurrentDomain.IsDefaultAppDomain())
        {
            Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);
    
            var currentAssembly = Assembly.GetExecutingAssembly();
            var otherDomain = AppDomain.CreateDomain("other domain");
            var ret = otherDomain.ExecuteAssemblyByName(currentAssembly.FullName, args);
    
            Environment.ExitCode = ret;
            return;
        }
    
        Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);
        Console.WriteLine("Hello");
    }
    

    使用非静态辅助入口点和 MarshalByRefObject 的快速示例...

    class Program
    {
        static AppDomain otherDomain;
    
        static void Main(string[] args)
        {
            otherDomain = AppDomain.CreateDomain("other domain");
    
            var otherType = typeof(OtherProgram);
            var obj = otherDomain.CreateInstanceAndUnwrap(
                                     otherType.Assembly.FullName,
                                     otherType.FullName) as OtherProgram;
    
            args = new[] { "hello", "world" };
            Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);
            obj.Main(args);
        }
    }
    
    public class OtherProgram : MarshalByRefObject
    {
        public void Main(string[] args)
        {
            Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);
            foreach (var item in args)
                Console.WriteLine(item);
        }
    }
    

    【讨论】:

    • 谢谢。是否有理由偏爱一种方法而不是另一种方法?
    • 第一个可能会更干净。它将允许您使用标准入口点,而不必创建需要跨应用程序域编组的对象。第二种方法更为典型。但它通常用于插件,而不是应用程序的主要入口点。
    • AppDomain 对象上还有一个.ExecuteAssembly(...) 方法,您可以提供指向另一个包含入口点的程序集的路径。这可能会带来更简洁的设计,但至少需要两个组件。
    • 我知道它必须是可能的......诀窍是在不引用 mscoree.tlb 的情况下弄清楚如何做到这一点。
    • 我不知道。
    【解决方案2】:

    你需要:

    1) 创建 AppDomainSetup 对象的实例,并使用您想要的域设置信息填充它

    2) 使用 AppDomain.CreateDoman 方法创建新域。带有配置参数的 AppDomainSetup 实例被传递给 CreateDomain 方法。

    3) 使用域对象上的 CreateInstanceAndUnwrap 方法在新域中创建对象的实例。此方法获取您要创建的对象的类型名并返回一个远程代理,您可以在您的主域中使用该代理与在新域中创建的对象进行通信

    完成这 3 个步骤后,您可以通过代理调用其他域中的方法。您也可以在完成后卸载域并重新加载它。

    MSDN 帮助中的这个topic 有非常详细的示例说明您需要什么

    【讨论】:

    • 这或多或少是我在其他地方看到的示例中看到的,但没有提供我仍然缺乏的任何信息。我只是调用 Application.Run(new MyForm) 吗?我是否从我的 Main 方法中删除所有现有的启动代码,将其插入一个新方法中,然后调用它来启动我的应用程序?以上都不是,因为我比我想象的更困惑?
    • 您尝试获取代理的对象必须是MarshalByRefObject,否则它只会尝试将副本序列化回原始 AppDomain。
    • @Dan 我从未尝试在非主域中运行 UI 相关的东西。就 UI 而言,恐怕你会遇到一些麻烦,主要是因为它是基于旧的非托管代码。如果你觉得大胆,试着把整个东西推到二级域,看看它是如何工作的。我的意思是在二级域中实例化Application类并调用Run方法
    • Matthew Whited 建议的递归输入方法工作正常,没有任何 GUI 问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-26
    • 2017-12-18
    • 2012-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多