即使处理异常IS,在VS2010调试器中获取未处理的异常

时间:2011-04-11 15:15:22

标签: visual-studio-2010 debugging unhandled-exception

我遇到VS2010的问题,其中调试器因未处理的异常而停止。但是,例外肯定是处理的。事实上,如果我把代码放在catch块中,当我按下F5时我会点击它。在调试 - >例外情况,我确实选中了“Thrown”复选框,因此IMO绝对没有理由弹出未处理的异常对话框...

我无法发布确切的代码,但很快就会处理样本。违规代码部分背后的基本思想是我有一个与硬件对话的线程,如果我有一个错误与它交谈,那么我抛出一个HardwareException。该线程使用BeginInvoke启动,当我调用EndInvoke时,异常会在回调处理程序中捕获。

当在调试器中抛出异常时,我得到一个消息框,上面写着'HardwareException不是由用户代码处理的。'但它是!!!

编辑 - 嗯,这让我发疯了。我有一些示例代码,它代表了我在我的应用程序中的代码,它看起来像这样:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting.Messaging;
using System.Threading;

namespace ConsoleApplication1
{
    public class HardwareException : ApplicationException
    {
        public HardwareException( string message) : base(message) {}
    }

    class Program
    {
        delegate void HardwareTestDelegate();

        static void Main(string[] args)
        {
            HardwareTestDelegate d = new HardwareTestDelegate( HardwareTestThread);
            d.BeginInvoke( HardwareTestComplete, null);
            while( true);
        }

        static void HardwareTestThread()
        {
            throw new HardwareException( "this is a test");
        }

        static void HardwareTestComplete( IAsyncResult iar)
        {
            try {
                AsyncResult ar = (AsyncResult)iar;
                HardwareTestDelegate caller = (HardwareTestDelegate)ar.AsyncDelegate;
                caller.EndInvoke( iar);
            } catch( Exception ex) {
                Console.WriteLine( "Should see this line without getting an unhandled exception message in the IDE");
            }
        }
    }
}

我从线程中抛出了我的HardwareException,然后在调用EndInvoke时处理异常。我猜墨菲是对的,因为当我运行这个示例代码时,它会做我所期望的 - 即IDE中没有弹出未处理的异常错误消息!

2 个答案:

答案 0 :(得分:2)

以下是Microsoft的回复,案例111053102422121. Allen Weng 撰写以下内容:

分析:

有关您的信息,当您调用EndInvoke()时,CLR将在回调中重新抛出异常。下面是EndInvoke()的简化版本:

public object EndInvoke(IAsyncResult asyncResult)
{
    using (new MultithreadSafeCallScope())
    {
        ThreadMethodEntry entry = asyncResult as ThreadMethodEntry;
         ............
        if (entry.exception != null)
        {
            throw entry.exception;
        }
     }
}

如果提供了异常处理程序,异常将在回调函数或异步方法中处理。这是如何在没有附加调试器的情况下工作的。

当您在VS.NET中运行它时,调试器似乎只检查异步方法中是否存在异常处理程序。如果没有这样的处理程序,调试器会认为没有处理异常并弹出一条错误消息通知您。

建议:

当您单独运行应用程序时,应用程序应该按预期工作。如果错误消息在您的调试中很烦人,可以通过取消选中“异常”对话框中的“公共语言运行时异常”的“用户未处理”(Debug | Exceptions或按CTRL + ATL + E)来禁用它。或者您可以在异步方法中添加try / catch。在后一种情况下,异常设置为null,不会在EndInvoke()中重新抛出。

答案 1 :(得分:0)

我遇到了同样的问题,所以我会为后人发布这个可行​​的解决方法:

在将代码抛出到.NET代码中的代码中(上例中的HardwareTestThread()),捕获被抛出的异常并将其包装在某些深奥的.NET异常类型中,您可以为其禁用“user- “调试>例外”对话框中未处理的“选项”。对于我的情况,我需要允许IOException通过某些.NET代码传播回我的代码,所以我只是捕获了IOException并包装在AppDomainUnloadedException中,然后让它通过.NET代码传播回我的catch块。我之所以选择AppDomainUnloadedException,是因为默认情况下取消选中了user-unhandled,它位于System.dll程序集中,因此它已经在我的项目中导入,但任何异常都应该有效,只要你禁用“user-unhandled”选项对于它而言,您并不关心调试器将来不会破坏该类型的异常。

这是我的代码,它包含了我需要传播的IOException:

public override int Read(byte[] buffer, int offset, int count)
{
    try { return innerStream.Read(buffer, offset, count); }
    catch (IOException ex) { throw new AppDomainUnloadedException("Exception from innerStream: " + ex.Message, ex); }
}

这是我的代码,我在它需要传播的.NET代码的另一端捕获它:

try { bytesRead = sslStream.Read(buffer, offset, count); }
catch (Exception ex) { /* ex handled here. */ }