I have a situation where I need to create a (arguably dirty) soak test runner. The idea being to use something like Tasks or the ThreadPool to run a massive amount of the tests at one time.
The issue is that it will be using a lot of (poorly developed, by me) helper classes that use statics within them. This has never been an issue as everything was torn down and restarted after it was used. This means that when I start multiple threads in the same app domain, they use the same statics, and things get messy.
Note: it is an assumption based on testing I’ve been doing, I’m not 100% sure on that being the issue.
I’ve tried creating a new AppDomain (AppDomain.Create) and then created an instance of a class using it (domain.CreateInstanceFromAndUnwrap), and it creates the instance, and I can call methods on it. The problem is that it doesn’t seem to be running in the new AppDomain.
Here’s the code I have so far:
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);
}
}
Now, I would expect that the RunProcess() method is executed in the domain, but the DomainID is still the same, and therefore it’s hitting the issue with the statics colliding.
Now, I did created a separate console app, and the commented out line shows the code I used to run it. This DID run in the new domain, but the question is why.
I’m happy to be pointed in the direction of some bedtime reading on how this works, I’ve ‘d for the past day and I think I must just not be using the right terms.
Any help is much appreciated.
Thanks,
Martin
There are two ways to expose objects over AppDomain boundaries:
Serializable– serializes the object, so you get a copy.MarshalByRefObject– creates a proxy to your object, using remoting.You need the latter for your
ProcessRunnerclass.Make your class inherit from
MarshalByRefObject:When you instantiate your class in the second AppDomain, you get a proxy. The example in the documentation for
MarshalByRefObjecton MSDN should also help you – it demonstrates almost exactly what you are trying to do.