【发布时间】:2011-07-24 17:26:25
【问题描述】:
我们正在使用 System.AddIn 将加载项加载到单独的子 AppDomain 中,如果加载项 AppDomain 有未处理的异常,我们将卸载它。
因为 .NET 从 2.0 版开始的默认行为是在任何 AppDomain 有未处理的异常时终止整个进程,因此我们通过在 App.config 中使用“legacyUnhandledExceptionPolicy”选项然后手动终止进程来做到这一点如果未处理的异常在主 AppDomain 中,或者在加载项中卸载相应的 AppDomain。
这一切都很好,除了一个小问题:未处理的异常总是从子 AppDomain 冒泡到主 AppDomain,如果它们不可序列化,它们就无法成功跨越 AppDomain 边界。
相反,我们在主 AppDomain 中以 UnhandledException 的形式出现 SerializationException,导致我们的应用程序自行关闭。
我能想到几个可能的解决方案:
我们无法为未处理的 SerializationExceptions 取消进程(糟糕)。
我们可以阻止异常从子 AppDomain 传播到主 AppDomain。
我们可以用可序列化的异常替换不可序列化的异常,可能使用序列化代理和序列化绑定。 [编辑:请参阅结尾,了解为什么使用代理无法实现这一点]
但是第一个非常可怕,我一直未能弄清楚如何使用跨 AppDomain 远程处理执行其他任何一个选项。
谁能给点建议?任何帮助表示赞赏。
使用以下 App.config 重现创建控制台应用程序:
<?xml version="1.0"?>
<configuration>
<runtime>
<legacyUnhandledExceptionPolicy enabled="true"/>
</runtime>
</configuration>
还有如下代码:
class Program
{
private class NonSerializableException : Exception
{
}
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += MainDomain_UnhandledException;
AppDomain childAppDomain = AppDomain.CreateDomain("Child");
childAppDomain.UnhandledException += ChildAppDomain_UnhandledException;
childAppDomain.DoCallBack(
() => new Thread(delegate() { throw new NonSerializableException(); }).Start());
Console.ReadLine();
}
static void MainDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine("Main AppDomain Unhandled Exception: " + e.ExceptionObject);
Console.WriteLine();
}
static void ChildAppDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine("Child AppDomain Unhandled Exception: " + e.ExceptionObject);
Console.WriteLine();
}
}
编辑:我使用反射器查看是否有任何方法可以访问跨 AppDomain 远程处理中使用的 BinaryFormatter,但它最终出现在 CrossAppDomainSerializer 类中的以下代码中:
internal static void SerializeObject(object obj, MemoryStream stm)
{
BinaryFormatter formatter = new BinaryFormatter();
RemotingSurrogateSelector selector = new RemotingSurrogateSelector();
formatter.SurrogateSelector = selector;
formatter.Context = new StreamingContext(StreamingContextStates.CrossAppDomain);
formatter.Serialize(stm, obj, null, false);
}
所以它在方法中本地创建格式化程序,显然没有办法附加我自己的代理......我认为这使得在这个方向上的任何努力都是徒劳的。
【问题讨论】:
-
嘿,詹姆斯,你找到解决办法了吗?
-
@Joshjje,不是一个好的解决方案......我们最终只处理了每个 AppDomain 中未处理的异常,然后让 AppDomain 从那里卸载自己。这显然需要信任每个加载项来设置这个系统,谢天谢地,我们可以为我们的应用程序。不过,我没有找到从主 AppDomain 中管理整个过程的方法。
标签: c# .net exception serialization appdomain