.Net framework introduces a new concept called application domains that provides code isolation within a process enviornment. These domains contain objects/assemblies/threads that can be instantiated at runtime and unloaded at runtime. This allows for a more stable application which also providing a mechanism to load/unload plugable components without having to compromise application runtime. (or the runtime host, as these kind of applications that load other applications is called).
The AppDomain class is used to create, load and work with application domains in .Net framework. I setout to work on a project that requires loading assemblies and creating local/remote objects at runtime. These objects (also called agents..yes the DistributedComuting course project) are autonomous. they just require an execution enviornment and they will work themself. They can create threads to carry out the work they are programmed to work on. A single thread at application level is supposed to deal with these agents. These can be cloned, migrated , suspended and/or destroyed.
The problem arised when loading multi-threaded agents inside my application at runtime. An agent can create multiple threads and the runtime has no information about which threads were created by which agent. Unloading the agent normally (using the dispose function which shuts off the threads this agent created smartly) is an ideal way of doing this. (since the agent itself knows the threads it has made and can dispose them). But if there is some kind of mishap during this process (or agent falls sick, or well..anything), all threads might not get destroyed. The object will be removed from the memory leaving the poor threads confused hence comes down our application crashing. There can be ways to create a single thread for an agent at my application level and make sure that all the rest of the threads are its children and die when this thread dies/suspends etc (Thats hard to achieve and a lot of code will have to be written just to tackle this problem). Also unfortunately its not possible to create a parent/child relationship between managed (or for that matter unmanged) threads. Infact Windows does not have the facility of parent/child relationship of threads(though it does for processes. The reasons are out of scope of this page. Refer to Chapter 6 of Programming Application for Microsoft Windows by Jeffery ritcher for some internals on threading under windows.) Also, considering the suspension issue of a process, since windows does not schedule processes but it schedules threads, to suspend a procesd requires suspending all the contained threads (naive approach). In our problem, we might need to suspend a single Agent (remember agents can create multiple threads). Unless we have an architecture to do so, it will be hard to know which thread is working for which agent. One way is to create a seperate process for each agent, but the overhead of creating/destroying processes, suspending processes etc is a lot under windows though in unix enviornment that might be a feasible idea. Infact thats how its carried out in a lot of of the unix applications. Again, that might create zombie issues, issues with interprocess communication etc. But that, of course is the best alternative.). Also, in a server envionrment (atleast in windows) running applications (in our case, Agents) under a single process is more scalable.
In .Net, Application Domains solves this problem (and hence this article). MSDN introduces Application Domains as follows :
“Application domains provide a more secure and versatile unit of processing that the common language runtime can use to provide isolation between applications. You can run several application domains in a single process with the same level of isolation that would exist in separate processes, but without incurring the additional overhead of making cross-process calls or switching between processes. The ability to run multiple applications within a single process dramatically increases server scalability.”
Application domains are usually used by runtime hosts such as Internet explorer which load 3rd party plugins and addon applications within their process. IE creates application domains for each addon and when one fails, it (well…supposedly) does not bring down the whole process. (unless of course of the glitch happned in the IE core itself which is mostly the case).
Enough introduction to Application domains, lets come to the point. We need to create objects from the loaded assembly. These objects can create multiple threads and we need a way to isolate these threads from other objects’ threads within the same application so that they dont crash the application. Also we need to track which objects created which threads. So we create a seperate application domain for each of these objects. These application domains will serve the threads. We will load/unload these domains (consequently loading/unloading the objects and the threads they have created).
Starting off with the object itself, I have a simple object that creates a thread and within that thread keeps printing which application domain it belongs to. (“Say my name!.. Say my name!!!….”). :p simple enough? He’re the code. Its not one of the best codes, but oh well bear with me.
public class MyClass: MarshalByRefObject
public void ThreadFunc()
public void MyFunc()
Thread t = new Thread(new ThreadStart(ThreadFunc));
We compile this code to a dll called classLibrary1.dll. Now in my application ill load this dll using reflection. ill create two application domains and create two objects of this class in both application domains, shut down one application domain and we’ll see waht happens.
static void Main(string args)
AppDomain appDomain1 = AppDomain.CreateDomain(“ad1”);
AppDomain appDomain2 = AppDomain.CreateDomain(“ad2”);
Assembly asm = Assembly.LoadFrom(“ClassLibrary1.dll”);
Type types = asm.GetTypes();
MyClass mc = (MyClass)appDomain1.CreateInstanceAndUnwrap(asm.FullName,types.FullName);
MyClass mc2 = (MyClass)appDomain2.CreateInstanceAndUnwrap(asm.FullName, types.FullName);
As you can see, the objects created within one Application domains create threads in that application domain and do not interfere with the other application domains. This is a very* simple program to show how application domains can be created and how threads work under application domains. We can improve on this furtur by creating a dictionary of objects and their application domains to keep track of which object instance is in which application domain etc. But i guess this will get you going. Ill blog soon about how to unload faulty objects from the application without having to screw up the application itself. :p