Click here to Skip to main content
15,898,735 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hi,

I need some help about an unhandle excetion throw from a sub domain when i invoke a method by reflection.

To explain the context of the problem :
I have a console application written(framework 3.5 c#) and i have an assembly(1) file written in dotnet too.
From this console application, i have created an another app domain and in this new app domain i invoke by reflection a call to a method from an object who is in this assembly(1).
But the big difficult is when the method is invoked and when an exception is throw : i can't catch this exception and i have a big message error in the output console who beginning by "unhandle exception ....etc..."

I tried to souscribe to the unhandleException of the AppDomain but nothing done.

Can you help me?

Thanks you,
.
Posted
Comments
Sergey Alexandrovich Kryukov 24-Jan-12 21:35pm    
After the answering, I realized that the question itself is pretty interesting; I voted 5.
--SA

1 solution

Yes, this is a real problem, not very easy one: let's say, you have started with Application Domain and created another application domain. This is really what you had to do if you need to load some assembly as a plug-in using System.Reflection and need to unload it on a regular basis and load another one. This is because there is no a way to unload a loaded assembly, you can only unload the whole Application Domain.

So here is your first option: you need to review your design and see if you really need using a separate Application Domain. If you are not unloading anything in some cycle, you should better load your assembly in your current Application Domain. That was a suggestion just in case. I hope your design is well based, so let's assume you really need to unload the Application Domain for the next step.

Now, let's assume you are calling some method in the Application Domain in the thread you are using in your host Application Domain. This is quite possible; the only problem is that Application Domains are isolated in data; you share the stack, but the heap and static memory storage are not shared between the Application Domain, but strongly isolated, in the same way as different processes. That said: to pass data, you can only need IPC (Inter-Process Communication). When you throw an exception in one Application Domain, you can catch it the other Application Domain. This is because the propagation of exceptions is some special kind of jumps over the stack of one thread. But — when you catch the exception beyond the Application Domain boundary, you cannot get exception information itself, as the boundary between Application Domains is not transparent for data. This is exactly what you observe.

So, what to do in this case? Let's say you call some method across the Application Domain using System.AppDomain.DoCallback (please see all the links below). How to pass some data to be used on the other side of Application Domain boundary? Right, by using IPC. The class System.AppDomain has the simplified IPC facility, GetData/SetData. You can share some data cells on both sides of the Application Domain boundary identified with some keys of the string type. As the strings for the keys are constants, you can have identical string values in both domains. At to the values passed, they are of the type System.Object and are serialized and deserialized behind the scene, so the type of data should be serializeable (please see the last link below).

So, the scenario would using some kind of what I call "exception thunk", which is applicable in many cases, such as using APIs based on different technologies, remote APIs and more. You can put some data in the Application Domain using SetData. The delegate executed in other Application Domain should read this data using GetData, then it should perform the operation and catch all the exceptions before return. This is the key. In the exception handler, the delegate code should pack required exception information in some serializeable data structure and put it in the cell dedicated for exception information using SetData. The calling part of the code executing in the host Application Domain should pick up this exception information using GetData and use it. To complete the "thunk", this part of code can actually throw a brand new exception based on received exception information.

So we the exception itself was caught immediately on the stack, and the exception information was carried over the bridge over the boundary between Application Domains ("thunk") which is based on System.ApplicationDomain.SetData/GetData using embedded IPC and serialization.

Please see:
http://msdn.microsoft.com/en-us/library/system.appdomain.aspx[^],
http://msdn.microsoft.com/en-us/library/system.appdomain.docallback.aspx[^],
http://msdn.microsoft.com/en-us/library/37z40s1c.aspx[^],
http://msdn.microsoft.com/en-us/library/system.appdomain.getdata.aspx[^],
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializable.aspx[^].

I've actually implemented this techniques and it worked well.

Please also see my past solutions I sent in response to questions on related topics:
Create WPF Application that uses Reloadable Plugins...[^],
AppDomain refuses to load an assembly[^],
code generating using CodeDom[^].

—SA
 
Share this answer
 
v3
Comments
hemigueti 25-Jan-12 14:54pm    
I tried to apply your technique but the problem can't resolve.
I catch the exception from the sub domain and put it in the default application domain property "SetData" and the value correctly but the application always crash.
For more on this exception, it's that in the sub application domain the call method is from an external component loaded(Assembly.Load(pathFile)) in this sub domain and not in the default application domain.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900