【问题标题】:AppDomain unhandled exceptionsAppDomain 未处理的异常
【发布时间】: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{})中捕获异常。

【问题讨论】:

    标签: c# exception-handling appdomain


    【解决方案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】:

    我的猜测是在处理异常时未调用处理程序。即通过上面的 try{}catch{}。

    【讨论】:

      【解决方案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】:
        1. FirstChanceException 着火了。
        2. 任何catch 块都会被执行。
        3. 如果块中没有catch 块或throw,则UnhandledException 触发

        您的catch 块可确保UnhandledException 不会触发。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-07-24
          • 1970-01-01
          • 2011-11-19
          • 1970-01-01
          • 1970-01-01
          • 2011-01-16
          相关资源
          最近更新 更多