应用域切换

时间:2011-10-19 22:39:48

标签: c# multithreading appdomain

我有一种情况需要创建一个(可以说是脏的)浸泡测试运行器。想法是使用诸如Tasks或ThreadPool之类的东西来同时运行大量的测试。

问题在于它将使用很多(由我开发的)辅助类,它们在其中使用静态。这从来都不是问题,因为一切都被拆除并在使用后重新启动。这意味着当我在同一个应用程序域中启动多个线程时,它们会使用相同的静态,而且事情会变得混乱。

注意:这是基于我一直在做的测试的假设,我不是100%肯定这就是问题。

我尝试创建一个新的AppDomain(AppDomain.Create),然后使用它创建一个类的实例(domain.CreateInstanceFromAndUnwrap),然后创建实例,我可以在其上调用方法。问题是它似乎没有在新的AppDomain中运行。

这是我到目前为止的代码:

    static void CallBack(BasePerfTest bpf)
    {
        Console.WriteLine("CurrentAppDomain (WithinCallback): {0}", Thread.GetDomain().Id);
        AppDomain newdomain = AppDomain.CreateDomain(Guid.NewGuid().ToString());
        //newdomain.ExecuteAssembly(".\\PerformanceTestRunner.exe", new string[] { bpf.ToString() });
        ProcessRunner pr = (ProcessRunner)newdomain.CreateInstanceFromAndUnwrap(Assembly.GetExecutingAssembly().Location, "PerformanceTesting.ProcessRunner");
        pr.RunProcess(bpf);
    }

}
[Serializable]
public class ProcessRunner
{
    public void RunProcess(BasePerfTest bpf)
    {
        Console.WriteLine("CurrentAppDomain (WithinPR): {0}", Thread.GetDomain().Id);
    }

}

现在,我希望RunProcess()方法在域中执行,但DomainID仍然是相同的,因此它会遇到静态冲突的问题。

现在,我确实创建了一个单独的控制台应用程序,注释掉的行显示了我用来运行它的代码。此DID在新域中运行,但问题是原因。

我很高兴能够指出一些睡前阅读的方向,这是关于它是如何工作的,我已经过去一天了,我想我一定不能使用正确的术语。

非常感谢任何帮助。

谢谢, 马丁

2 个答案:

答案 0 :(得分:4)

有两种方法可以通过AppDomain边界公开对象:

  • Serializable - 序列化对象,以便获得副本。
  • MarshalByRefObject - 使用远程处理为您的对象创建代理。

您的ProcessRunner课程需要后者。

让您的班级继承自MarshalByRefObject

public class ProcessRunner : MarshalByRefbject
{
    public void RunProcess(BasePerfTest bpf)
    {
        Console.WriteLine("CurrentAppDomain (WithinPR): {0}", Thread.GetDomain().Id);
    }
}

当您在第二个AppDomain中实例化您的类时,您将获得一个代理。 MSDN上MarshalByRefObject文档中的示例也应该对您有所帮助 - 它几乎可以证明您正在尝试做什么。

答案 1 :(得分:2)

您的ProcessRunner类必须从System.MarshalByRefObject继承。发生的事情是该对象实际上是在辅助应用程序域中创建的,但是当您将其分配给本地“pr”变量时,它会通过值将其编组回您的主应用程序域,实际上会在其中创建ProcessRunner的第二个实例。主appdomain。如果从MarshalByRefObject继承,那么pr将获得一个透明的代理对象,该对象将调用转发给驻留在辅助appdomain中的对象。