繁体   English   中英

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

[英]Visual Studio 2010 doesn’t stop at an unhandled exception inside a Socket.BeginReceive() callback - why?

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

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

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

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显然吞下了这个异常? 我能否像通​​常那样让它在例外中突破?

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

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

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

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

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

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

屏幕截图O'胜利:

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

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

  1. 如果没有异常在调试- >例外对话框明确检查和选项- >调试- >“启用仅我的代码”(EJMC) 没有被选中,然后在任何回调抛出的异常不会有第一次机会异常打破( FCE)

  2. 如果没有异常在调试- >例外对话框明确检查,EJMC 选中,然后在抛出的异常TCPListener的回调 FCE突破,但FCE在不会破坏Socket的回调

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

  3. 如果System.InvalidOperationException (或System )在调试- 检查 >例外,然后在任何回调抛出一个适当的异常 FCE打破,无论是否EJMC检查与否。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM