简体   繁体   English

如何处理从另一个AppDomain引发的异常?

[英]How to handle exceptions thrown from another AppDomain?

I have a WPF bootstrapper application: it loads my application UI from a separate assembly into another AppDomain then shows the main window. 我有一个WPF引导程序应用程序:它将应用程序UI从一个单独的程序集加载到另一个AppDomain中,然后显示主窗口。 So the application UI runs from this subdomain. 因此,应用程序UI从此子域运行。

The question : How to handle exceptions in the main domain thrown from the subdomain? 问题 :如何处理从子域抛出的主域中的异常?

Why? 为什么? Because my goal is to implement an application updater: when the client realizes that there is a new version is available it would throw some SystemException with a specific message. 因为我的目标是实现应用程序更新程序:当客户端意识到有可用的新版本时,它将抛出带有特定消息的SystemException

I want the host domain to handle this specific exception: unload the subdomain, download the latest assembly version from the internet and recreate the subdomain by reloading the most up-to-date DLLs. 我希望主机域能够处理此特定异常:卸载子域,从Internet下载最新的程序集版本,并通过重新加载最新的DLL重新创建子域。

The problem : It seem to me that an unhandled exception in any AppDomain causes the whole thread to terminate. 问题 :在我看来,任何AppDomain中未处理的异常都会导致整个线程终止。 I found some blog post stating that one should turn on the legacyUnhandledExceptionPolicy to switch back to the .NET 1.0/1.1 legacy mode exception handling, but I'm not sure that I want to use this legacy stuff in my application. 我发现一些博客文章指出应该打开legacyUnhandledExceptionPolicy切换回.NET 1.0 / 1.1遗留模式异常处理,但是我不确定我是否要在应用程序中使用该遗留内容。

Is there any other way to properly handle exception in other AppDomains? 还有其他方法可以正确处理其他AppDomain中的异常吗?

The general approach to handle custom exception 'E' caused in AppDomain-A is to have this exception defined in an assembly that is registered in GAC. 处理在AppDomain-A中导致的自定义异常“ E”的一般方法是在GAC中注册的程序集中定义此异常。 So, AppDomain-A references this common assembly and AppDomain-B (observer) references this assembly. 因此,AppDomain-A引用此公共程序集,而AppDomain-B(观察者)引用此程序集。

This is because the Exception class is [Serializable] and will be passed by value over the domain boundary. 这是因为Exception类是[Serializable]并且将通过值在域边界上传递。 Once you get the blob through the boundary, CLR will try to deserialize it. 一旦通过边界获取了Blob,CLR就会尝试对其进行反序列化。 So CLR must be able to find appropriate type for deserialization. 因此,CLR必须能够找到合适的反序列化类型。 So, deserialization will lookup for the exception type according to standard rule. 因此,反序列化将根据标准规则查找异常类型。

There could be of course another solutions with type resolution behavior changes diving deep serialization/deserialization mechanisms. 当然,可能存在另一种解决方案,其类型解析行为更改将采用深层序列化/反序列化机制。

In case if you want to learn more, just read Jeffry's book chapter about the serialization mechanisms and versioning. 如果您想了解更多信息,请阅读Jeffry的书中有关序列化机制和版本控制的章节。

If the appdomain is running on another thread use the AppDomain.UnhandledException event handler to handle uncaught exceptions in your new appdomain 如果appdomain在另一个线程上运行,请使用AppDomain.UnhandledException事件处理程序来处理新appdomain中未捕获的异常

newAppDomain.UnhandledException += new UnhandledExceptionEventHandler(ErrorHandler);

public void ErrorHandler(object sender, UnhandledExceptionEventArgs args) 
{
    Exception e = (Exception) args.ExceptionObject;
    // handle here
}

A different approach is to unload the appdomain using AppDomain.Unload, the assembly in the appdomain should handle AppDomain.DomainUnload event to close down gracefully. 另一种方法是使用AppDomain.Unload卸载appdomain,appdomain中的程序集应处理AppDomain.DomainUnload事件以正常关闭。 You can then spawn a new appdomain and start again. 然后,您可以产生一个新的appdomain并重新开始。

This is assuming you are running the new app domain on a seperate thread, otherwise you will need to handle the exception around the calling code from the parent, becuase an unhandled exception on the main thread will abort the process. 这是假设您在单独的线程上运行新的应用程序域,否则您将需要处理来自父级的调用代码周围的异常,因为主线程上未处理的异常将中止该过程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM