AppDomain 未处理的异常
Posted
技术标签:
【中文标题】AppDomain 未处理的异常【英文标题】:AppDomain unhandled exceptions 【发布时间】:2013-03-22 11:31:46 【问题描述】:有很多主题涵盖了这个问题。不过我还是有问题。
我将程序集加载到新的AppDomain
中,如下所示:
public void Run()
//There's the problem.
//As Panos Rontogiannis mentioned the thread is created in default AppDomain
new Thread(RunApp).Start();
private void RunApp()
try
AppDomain.CreateDomain("domain name").ExecuteAssembly("path to assembly");
catch (Exception _e)
MessageBox.Show("Unhandled Exception.\n" + _e);
在加载程序集的 Main 方法中,我将处理程序订阅到 UnhandledException
事件:
AppDomain.CurrentDomain.UnhandledException += handleException;
处理程序本身:
public static void handleException(object a_s, UnhandledExceptionEventArgs a_args)
var _e = (Exception)a_args.ExceptionObject;
//Static loger class method
Loger.WriteError(_e.GetType().ToString(), _e.Message, "default solution");
但是,无论在加载的程序集中哪里抛出异常,处理程序都不会参与其中。我只在默认的AppDomain
(第一个try catch
)中捕获异常。
【问题讨论】:
【参考方案1】:很可能,您无法处理新AppDomain
中的异常的原因是它不是从在该AppDomain
中创建的线程中抛出的。从AppDomain.UnhandledException 上的文档来看,这并不是很直接。有趣的部分如下:
只有当线程的整个堆栈都有 在没有找到适用的异常处理程序的情况下展开,因此 可以引发事件的第一个位置是在应用程序域中 线程起源。
现在,如果执行抛出代码的线程是在您的主AppDomain
中创建的(就像控制台应用程序的主线程),那么您应该在主AppDomain
中添加一个处理程序。请注意,如果抛出的异常类型未在主 AppDomain 中加载,.NET 的程序集加载器将尝试从应用程序的基本目录和探测路径加载它。如果这些与子 AppDomain
不同,则程序集将不会被解析并会引发(其他)异常。
【讨论】:
你是对的。ExecuteAssembly
在默认 AppDomain
中创建的新 Thread
中调用。但是处理新 AppDomain
中加载的组件中的异常是至关重要的。
@Wazelin 通过处理它,您的意思是简单地记录它。对于未处理的异常,您无能为力。如果从子 AppDomain 中创建的线程抛出未处理的异常,则 AppDomain 注定要失败,应用程序也注定要失败。如果您想将您的应用程序与其他代码隔离开来,则需要使用不同的进程。【参考方案2】:
发生这种情况的原因有很多。 http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx 的事件文档详细介绍了这种复杂性如果似乎没有任何内容适用,您能否发布重现代码?
【讨论】:
恕我直言这个答案应该是评论【参考方案3】:我的猜测是在处理异常时未调用处理程序。即通过上面的 trycatch。
【讨论】:
【参考方案4】:我真的不明白为什么处理程序没有被调用。
我最终在加载程序集的 Main 方法中使用了 FirstChanceException 而不是 UnhandledException。像这样:
AppDomain.CurrentDomain.FirstChanceException +=
(obj, e) => Loger.WriteError(
e.Exception.ToString(),
e.Exception.Message,
"default solution"
);
【讨论】:
它可能适合您的事业,但我对此表示怀疑。第一次机会异常事件不与未捕获的异常相同。简而言之,无论引发的每个异常是否最终都未被代码处理(捕获块而没有重新抛出),您都会收到此事件。 好吧,因为我只将它用于记录目的,我认为没关系。异常会被记录下来,如果存在,处理程序会继续工作。 是的,但请记住,某些代码(甚至在 .net 框架本身中)在内部使用异常,这些代码不会浮出水面,并且可能会用“虚假”异常掩盖您的日志记录。当然,您的里程可能会有所不同。 感谢您的警告。我还没想过。【参考方案5】:这是一个迟到的回复,但如果你问我这似乎工作正常(VS2012/.NET 4.5),当然需要在调用 ExecuteAssembly 之前注册异常处理程序:(我有一个导致访问的子进程通过写入空引用(不安全代码)来强制崩溃并触发以下 HandleException 的违规行为:
public static void HandleException(object a_s, UnhandledExceptionEventArgs a_args)
var _e = (Exception)a_args.ExceptionObject;
Console.WriteLine(_e.GetType().ToString(), _e.Message, "default solution");
public void StarProcessWithinAppDomain(string fileName)
try
// New appdoamin / check exception isolation level
AppDomain sandBox = AppDomain.CreateDomain("sandBox");
try
AppDomain.CurrentDomain.UnhandledException += HandleException;
sandBox.ExecuteAssembly(fileName);
catch (Exception ex)
Console.WriteLine("An error occurred (inner) within AppDomain, executing \"0\":" + "\n" + ex.Message, fileName);
finally
AppDomain.Unload(sandBox);
catch (Exception ex)
Console.WriteLine("An error occurred within AppDomain, executing \"0\":" + "\n" + ex.Message, fileName);
【讨论】:
【参考方案6】:FirstChanceException
着火了。
任何catch
块都会被执行。
如果块中没有catch
块或throw
,则UnhandledException
触发
您的catch
块可确保UnhandledException
不会触发。
【讨论】:
以上是关于AppDomain 未处理的异常的主要内容,如果未能解决你的问题,请参考以下文章
当我加载的另一个 AppDomain 引发未处理的异常时,我可以隔离我当前的 AppDomain 以防被拆除吗?
是否可以防止子 AppDomain 中的未处理异常导致主进程崩溃?
AppDomain.UnhandledException 自动重新抛出已处理的异常
Appdomain.Load(AssemblyName) 引发文件未找到异常