通过inkove(reflection)调用方法时,如何捕获从子域引发的未处理异常 [英] how to Catch an unhandled exception thrown from a sub domain when calling a method by inkove(reflection)

查看:199
本文介绍了通过inkove(reflection)调用方法时,如何捕获从子域引发的未处理异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



当我通过反射调用方法时,我需要一些有关子域异常处理抛出的帮助.

解释问题的背景:
我编写了一个控制台应用程序(框架3.5 c#),我也编写了一个用dotnet编写的assembly(1)文件.
在这个控制台应用程序中,我创建了另一个应用程序域,在这个新的应用程序域中,我通过反射从该Assembly(1)中的对象对方法的调用来调用.
但是最大的困难是何时调用该方法以及何时引发异常:我无法捕获此异常,并且我在输出控制台中遇到一个大消息错误,该错误消息的开头是未处理异常.... etc ..." "

我试图寻求AppDomain的unhandleException,但是什么也没做.

你能帮我吗?

谢谢
.

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,
.

推荐答案

是的,这是一个实际的问题,不是一个很简单的问题:假设您已经开始使用Application Domain并创建了另一个应用程序域.如果您需要使用System.Reflection将某些程序集作为插件加载,并且需要定期卸载它并加载另一个,则确实需要执行此操作.这是因为无法卸载已加载的程序集,只能卸载整个应用程序域.

因此,这是您的第一个选择:您需要检查设计,看看是否确实需要使用单独的应用程序域.如果您不打算在某个周期中卸载任何程序,则最好将程序集加载到当前的应用程序域"中.这是一个建议,以防万一.我希望您的设计基础良好,因此假设您确实需要卸载应用程序域以进行下一步.

现在,假设您正在宿主应用程序域中使用的线程中的应用程序域中调用某种方法.这是完全有可能的.唯一的问题是应用程序域被隔离在数据中;您共享堆栈,但是堆和静态内存存储不是在Application Domain之间共享,而是以与不同进程相同的方式完全隔离.就是说:要传递数据,您只需要IPC(进程间通信).在一个应用程序域中引发异常时,可以在另一个应用程序域中捕获该异常.这是因为异常的传播是在一个线程的堆栈上进行的某种特殊跳转.但是-当您在应用程序域边界之外捕获异常时,您将无法获取异常信息本身,因为应用程序域之间的边界对于数据而言不是透明的.这正是您所观察到的.

那么,在这种情况下该怎么办?假设您使用System.AppDomain.DoCallback在整个应用程序域中调用某种方法(请参见下面的所有链接).如何传递一些要在应用程序域边界另一端使用的数据?正确,使用IPC.类System.AppDomain具有简化的IPC工具GetData/SetData.您可以在由字符串类型的某些键标识的应用程序域"边界的两侧共享一些数据单元.由于键的字符串是常量,因此在两个域中都可以具有相同的字符串值.对于传递的值,它们的类型为System.Object,并且在后台进行序列化和反序列化,因此数据类型应可序列化(请参见下面的最后一个链接).

因此,该方案将使用某种我称为" exception thunk "的方法,该方法在许多情况下都适用,例如使用基于不同技术的API,远程API等.您可以使用SetData将一些数据放入应用程序域"中.在其他Application Domain中执行的委托应使用GetData读取此数据,然后应执行操作并在返回之前捕获所有异常.这是关键.在异常处理程序中,委托代码应在一些可序列化的数据结构中包装所需的异常信息,并使用SetData将其放入专用于异常信息的单元中.在主机应用程序域中执行的代码的调用部分应使用GetData使用它来获取此异常信息.为了完成"thunk"操作,这部分代码实际上可以根据收到的异常信息抛出全新的异常.

因此,我们将异常本身立即捕获到堆栈中,并且异常信息通过应用程序域("thunk")之间的边界跨过桥,该桥基于System.ApplicationDomain.SetData/GetData使用嵌入式IPC和序列化.

请参阅:
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 [ ^ ].

我实际上已经实现了这种技术,并且效果很好.

另请参阅我过去发送的有关相关主题问题的解决方案:
创建使用可重载插件的WPF应用程序... [ ^ ],
AppDomain拒绝加载程序集 [使用CodeDom生成代码 [
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


这篇关于通过inkove(reflection)调用方法时,如何捕获从子域引发的未处理异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆