什么时候.NET WinForms应用程序中的异常只是被吃掉而没有被捕获或冒泡到Windows异常?

时间:2022-03-21 01:51:42

In several places in our code, we notice that if running under debugger it'll show that there's an unhandled exception in the code, however if running outside the debugger it will just ignore the exception completely as if it were caught. We have an exception handler that pops up an error submit dialog that's hooked up to Application.ThreadException and AppDomain.CurrentDomain.UnhandledException And neither of those appear to be catching them either. We also log our exceptions and nothing appears in the log.

在我们的代码中的几个地方,我们注意到如果在调试器下运行,它将显示代码中存在未处理的异常,但是如果在调试器外部运行,它将完全忽略异常,就好像它被捕获一样。我们有一个异常处理程序,弹出一个连接到Application.ThreadException和AppDomain.CurrentDomain.UnhandledException的错误提交对话框。这些都不会捕获它们。我们还记录了我们的异常,日志中没有任何内容。

What are some possible reasons for this?

这有什么可能的原因?

Edit: It seems that it isn't dependent on the type of exception throw, but rather where it is thrown. This was tested by just adding:

编辑:似乎它不依赖于异常抛出的类型,而是它抛出的位置。仅通过添加以下测试:

throw new Exception("Test Exception");

It'll show up under debugger but doesn't show up outside, so in our case it's not a ThreadAbortedException or anything that's dependent on it being a specific type of exception.

它将显示在调试器下但不会显示在外部,因此在我们的示例中,它不是ThreadAbortedException或任何依赖于它的特定类型的异常。

6 个解决方案

#1


There are some special exceptions that don't get bubbled up or caught, it sounds like you're dealing with one of them: see ThreadAbortException

有一些特殊的异常不会被冒泡或被捕获,听起来你正在处理其中一个:请参阅ThreadAbortException

#2


Found one place where this could occur is if there's an exception in the UnhandledException event handler. An easy way to see this is this: In the Form.Load event handler throw any old exception. In the Application.ThreadException event put something similar to the following:

找到一个可能发生这种情况的地方是UnhandledException事件处理程序中是否有异常。一个简单的方法是这样:在Form.Load事件处理程序中抛出任何旧的异常。在Application.ThreadException事件中添加类似于以下内容:

static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
     string b = null;
     int i = b.Length;
}

Under debugger it'll show your exception was unhandled by user code, and then after that it'll show a null reference exception in the ThreadException handler, but if you run it outside the debugger it'll just swallow the exception like it was handled.

在调试器下,它将显示您的异常未被用户代码处理,然后它将在ThreadException处理程序中显示空引用异常,但如果您在调试器外部运行它,它只会吞下异常,就像处理它一样。

#3


If you try to modify the properties of a Windows Form control from a different thread the control was created in, you get an InvalidOperationException if there is a debugger attached, but it gets silently ignored otherwise.

如果您尝试从创建控件的其他线程修改Windows窗体控件的属性,如果连接了调试器,则会出现InvalidOperationException,但是否则会以静默方式忽略它。

More info on the issue can be found here:

有关该问题的更多信息,请访问:

http://msdn.microsoft.com/en-us/library/ms171728(VS.80).aspx

#4


Your code is invoked from the framework.

您的代码是从框架中调用的。

Sometimes, the framework wraps its calls in an exception handler.

有时,框架将其调用包装在异常处理程序中。

So, if there's an exception in your code, it may be (if there's an exception handler there in the framework) caught and ignored by the framework.

因此,如果您的代码中存在异常,那么框架可能会捕获并忽略(如果框架中存在异常处理程序)。

Maybe the debugger shows it as "unhandled" because, although there's a handler in the framework, there's no handler in your code? Or, because there's something strange about the handler in the framework, for example that it's an unmanaged, structured exception handler?

也许调试器将其显示为“未处理”,因为尽管框架中有一个处理程序,但代码中没有处理程序?或者,因为框架中的处理程序有些奇怪,例如它是一个非托管的,结构化的异常处理程序?

#5


Are you using .Net 1.0/1.1? There was a huge change in behaviour in the transition from 1.1 to 2.0. Before then exceptions raised on threads you created or ThreadPool threads would be swallowed silently by the frameworok and the thread would exit. Thankfully this behaviour has now been fixed.

你使用的是.Net 1.0 / 1.1吗?从1.1到2.0的过渡行为发生了巨大变化。在此之前,由您创建的线程引发的异常或ThreadPool线程将以静默方式吞下ThreadPorok,线程将退出。值得庆幸的是,此行为现已得到修复。

From MSDN:

Change from Previous Versions

The most significant change pertains to managed threads. In the .NET Framework versions 1.0 and 1.1, the common language runtime provides a backstop for unhandled exceptions in the following situations:

最重要的更改与托管线程有关。在.NET Framework 1.0和1.1版中,公共语言运行库在以下情况下为未处理的异常提供了一个支持:

  • There is no such thing as an unhandled exception on a thread pool thread. When a task throws an exception that it does not handle, the runtime prints the exception stack trace to the console and then returns the thread to the thread pool.

    在线程池线程上没有未处理的异常。当任务抛出它不处理的异常时,运行时将异常堆栈跟踪打印到控制台,然后将该线程返回到线程池。

  • There is no such thing as an unhandled exception on a thread created with the Start method of the Thread class. When code running on such a thread throws an exception that it does not handle, the runtime prints the exception stack trace to the console and then gracefully terminates the thread.

    在使用Thread类的Start方法创建的线程上没有未处理的异常。当在这样的线程上运行的代码抛出它不处理的异常时,运行时将异常堆栈跟踪打印到控制台,然后正常终止该线程。

  • There is no such thing as an unhandled exception on the finalizer thread. When a finalizer throws an exception that it does not handle, the runtime prints the exception stack trace to the console and then allows the finalizer thread to resume running finalizers.

    终结器线程上没有未处理的异常。当终结器抛出它不处理的异常时,运行时将异常堆栈跟踪打印到控制台,然后允许终结器线程恢复运行终结器。

#6


Kind of a stretch here, but could it be that you just have set your debugger to break when an exception is thrown, and not only for the unhandled ones?

这里有一种延伸,但是你可能只是设置你的调试器在抛出异常时中断,而不仅仅是未处理的异常?

#1


There are some special exceptions that don't get bubbled up or caught, it sounds like you're dealing with one of them: see ThreadAbortException

有一些特殊的异常不会被冒泡或被捕获,听起来你正在处理其中一个:请参阅ThreadAbortException

#2


Found one place where this could occur is if there's an exception in the UnhandledException event handler. An easy way to see this is this: In the Form.Load event handler throw any old exception. In the Application.ThreadException event put something similar to the following:

找到一个可能发生这种情况的地方是UnhandledException事件处理程序中是否有异常。一个简单的方法是这样:在Form.Load事件处理程序中抛出任何旧的异常。在Application.ThreadException事件中添加类似于以下内容:

static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
     string b = null;
     int i = b.Length;
}

Under debugger it'll show your exception was unhandled by user code, and then after that it'll show a null reference exception in the ThreadException handler, but if you run it outside the debugger it'll just swallow the exception like it was handled.

在调试器下,它将显示您的异常未被用户代码处理,然后它将在ThreadException处理程序中显示空引用异常,但如果您在调试器外部运行它,它只会吞下异常,就像处理它一样。

#3


If you try to modify the properties of a Windows Form control from a different thread the control was created in, you get an InvalidOperationException if there is a debugger attached, but it gets silently ignored otherwise.

如果您尝试从创建控件的其他线程修改Windows窗体控件的属性,如果连接了调试器,则会出现InvalidOperationException,但是否则会以静默方式忽略它。

More info on the issue can be found here:

有关该问题的更多信息,请访问:

http://msdn.microsoft.com/en-us/library/ms171728(VS.80).aspx

#4


Your code is invoked from the framework.

您的代码是从框架中调用的。

Sometimes, the framework wraps its calls in an exception handler.

有时,框架将其调用包装在异常处理程序中。

So, if there's an exception in your code, it may be (if there's an exception handler there in the framework) caught and ignored by the framework.

因此,如果您的代码中存在异常,那么框架可能会捕获并忽略(如果框架中存在异常处理程序)。

Maybe the debugger shows it as "unhandled" because, although there's a handler in the framework, there's no handler in your code? Or, because there's something strange about the handler in the framework, for example that it's an unmanaged, structured exception handler?

也许调试器将其显示为“未处理”,因为尽管框架中有一个处理程序,但代码中没有处理程序?或者,因为框架中的处理程序有些奇怪,例如它是一个非托管的,结构化的异常处理程序?

#5


Are you using .Net 1.0/1.1? There was a huge change in behaviour in the transition from 1.1 to 2.0. Before then exceptions raised on threads you created or ThreadPool threads would be swallowed silently by the frameworok and the thread would exit. Thankfully this behaviour has now been fixed.

你使用的是.Net 1.0 / 1.1吗?从1.1到2.0的过渡行为发生了巨大变化。在此之前,由您创建的线程引发的异常或ThreadPool线程将以静默方式吞下ThreadPorok,线程将退出。值得庆幸的是,此行为现已得到修复。

From MSDN:

Change from Previous Versions

The most significant change pertains to managed threads. In the .NET Framework versions 1.0 and 1.1, the common language runtime provides a backstop for unhandled exceptions in the following situations:

最重要的更改与托管线程有关。在.NET Framework 1.0和1.1版中,公共语言运行库在以下情况下为未处理的异常提供了一个支持:

  • There is no such thing as an unhandled exception on a thread pool thread. When a task throws an exception that it does not handle, the runtime prints the exception stack trace to the console and then returns the thread to the thread pool.

    在线程池线程上没有未处理的异常。当任务抛出它不处理的异常时,运行时将异常堆栈跟踪打印到控制台,然后将该线程返回到线程池。

  • There is no such thing as an unhandled exception on a thread created with the Start method of the Thread class. When code running on such a thread throws an exception that it does not handle, the runtime prints the exception stack trace to the console and then gracefully terminates the thread.

    在使用Thread类的Start方法创建的线程上没有未处理的异常。当在这样的线程上运行的代码抛出它不处理的异常时,运行时将异常堆栈跟踪打印到控制台,然后正常终止该线程。

  • There is no such thing as an unhandled exception on the finalizer thread. When a finalizer throws an exception that it does not handle, the runtime prints the exception stack trace to the console and then allows the finalizer thread to resume running finalizers.

    终结器线程上没有未处理的异常。当终结器抛出它不处理的异常时,运行时将异常堆栈跟踪打印到控制台,然后允许终结器线程恢复运行终结器。

#6


Kind of a stretch here, but could it be that you just have set your debugger to break when an exception is thrown, and not only for the unhandled ones?

这里有一种延伸,但是你可能只是设置你的调试器在抛出异常时中断,而不仅仅是未处理的异常?