Visual Studio 2010不会停止在Socket.BeginReceive()回调中的未处理exception – 为什么?

通常,在附加调试器时,即使“exception”对话框在“已抛出”列中没有exception类型的勾号,Visual Studio 2010也会在未处理的exception处停止。 这里的关键字未处理; 所述对话框仅指处理的exception。

但是,在下面的最小示例中,Visual Studio 2010不会停止在我的exception中,即使它作为第一次机会exception出现在立即窗口中:

编辑:我发布的第一个最小的例子是我收到的第一个答案修复,但不幸的是下面的例子仍然显示问题:

using System; using System.Net.Sockets; namespace SocketTest { class Program { static void Main(string[] args) { var listener = new TcpListener(8080); listener.Start(); AsyncCallback accepter = null; accepter = ar => { var socket = listener.EndAcceptSocket(ar); var buffer = new byte[65536]; AsyncCallback receiver = null; receiver = ar2 => { var bytesRead = socket.EndReceive(ar2); throw new InvalidOperationException(); socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, receiver, null); }; socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, receiver, null); listener.BeginAcceptSocket(accepter, null); }; listener.BeginAcceptSocket(accepter, null); Console.WriteLine("Feel free to connect to port 8080 now."); Console.ReadLine(); } } } 

如果你运行它,通过运行telnet localhost 8080连接到它,然后在telnet中键入任何字符,希望你会看到我看到的:程序只是默默地中止。

为什么Visual Studio显然吞下了这个exception? 我能否像通​​常那样让它在例外中突破?

(有趣的是,抛出BeginAcceptSocket回调内部确实会被捕获,就像在Thread.Start启动的普通线程中的exception一样。我只能通过抛出BeginReceive回调来重现该问题。)

这是CLR第4版中的一个已知错误。反馈文章就在这里 。 可能的解决方法是将框架目标更改为3.5版。 我只想引用反馈回复的相关部分:

我们已经调查了这个问题,并确定CLR v4.0中存在一个导致此问题的错误。 该进程会抛出exception(例如,您可以使用catch处理程序捕获它),但调试器未正确通知未处理的exception。 这导致进程似乎退出而没有来自调试器的任何关于发生的事情的指示。 我们已经调查了潜在的修复程序,但是所有修复程序都具有破坏其他function的中等风险。 因为产品周期很晚,所以我们认为不解决这个问题更安全,并且有可能造成新的错误。 我们将继续跟踪此问题,作为下一个发布周期的一部分。

该问题仅限于逃避托管代码的exception,其中线程是使用一些特定的API调用创建的:
新的System.Threading.Timer()
ThreadPool.UnsafeQueueNativeOverloapped
ThreadPool.BindHandle
ThreadPool.RegisterWaitForSingleObject。

在这种特定情况下,它是RegisterWaitForSingleObject()。

由于您在exception设置中只看到“Thrown”复选框,因此我怀疑您在调试设置中启用了“.Net Framework Source Stepping”。 如果启用“Just My Code”(禁用“.Net Framework Source Stepping”),您应该在exception设置对话框中获得“User-Unhandled”和“Thrown”复选框,您还将在调试器中捕获exception。

屏幕截图O’胜利:

屏幕截图显示调试器按预期在异常处停止

这是我到目前为止发现的:

  1. 如果在Debug-> Exceptions对话框中没有显式检查exception,并且未选中选项 – > Debugging – >“Enable Just My Code”(EJMC),则任何回调中抛出的exception都不会因First Chance Exception 中断( FCE)

  2. 如果在Debug-> Exceptions对话框中没有显式检查exception并且检查了EJMC,那么TCPListener的回调中抛出的exception与FCE中断,但在Socket的回调中不会与FCE中断

    一个。 抛出的exception不会Socket的回调中与FCE中断,即使TCPListener的阻塞AcceptSocket()被调用(因此没有侦听器的回调)。

  3. 如果在Debug-> Exceptions中选中了System.InvalidOperationException (或System ),则无论是否选中EJMC,任何回调中抛出的相应exception都将与FCE中断。

  4. 无论回调是指定为lambda还是指定为激活的用户函数,以上情况都是正确的

我不知道为什么VS不会在套接字回调中断开FCE,如果在Debug-> Exceptions中没有明确地检查exception(是什么使得套接字回调与侦听器回调不同)。