Visual Studio 2010 не останавливается на необработанном исключении внутри обратного вызова Socket.BeginReceive() - почему?

Обычно, когда отладчик подключен, Visual Studio 2010 останавливается при необработанном исключении, даже если в диалоговом окне Исключения нет отметки для типа исключения в столбце "Брошенный". Ключевое слово здесь необработанное; указанный диалог относится только к обработанным исключениям.

Однако в следующем минимальном примере Visual Studio 2010 не останавливается на исключение для меня, даже если оно появляется в окне Immediate как исключение из первого шанса:

РЕДАКТИРОВАТЬ: Первый минимальный пример, который я опубликовал, был исправлен первым ответом, который я получил, но, к сожалению, следующий пример все еще обнаруживает проблему:

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.)

Ответ 1

Это известная ошибка в версии CLR 4. Здесь приведена ссылка . Возможным обходным решением является изменение целевой рамки для версии 3.5. Я просто процитирую соответствующую часть ответа обратной связи:

Мы исследовали проблему и определили, что в CLR есть ошибка v4.0, который вызывает это. Процесс делает исключение (вы можете поймать его с помощью обработчика catch), но отладчик не был должным образом уведомлены о необработанном исключении. Это вызывает процесс появиться, чтобы выйти без каких-либо указаний от отладчика о том, что получилось. Мы исследовали потенциальные исправления, однако все исправления имели умеренный риск нарушения других функций. Потому что было очень поздно в цикле продуктов, мы решили, что было бы безопаснее не исправлять это проблема и риск создания новых ошибок. Мы продолжим отслеживать эту проблему как часть нашего следующего цикла выпуска.

Проблема ограничивается исключениями, которые управляют управляемым кодом, где поток был создан с использованием нескольких специальных вызовов API:
новый System.Threading.Timer()
ThreadPool.UnsafeQueueNativeOverloapped
ThreadPool.BindHandle
ThreadPool.RegisterWaitForSingleObject.

В этом конкретном случае это RegisterWaitForSingleObject().

Ответ 2

Поскольку вы видите флажок "Брошенный" в настройках исключения, мое подозрение в том, что в настройках отладки включено ".Net Framework Source Stepping". Если вы включите "Just My Code" (который отключает "Шаблоны Source Framework Step Stepping" ), вы должны установить флажки "Пользовательские необработанные" и "Брошенные" в диалоговом окне настроек исключения, и вы также поймаете исключение в отладчике.

Экранный снимок O 'Victory:

Screenshot showing the debugger halted at the exception as expected

Ответ 3

Это то, что я обнаружил до сих пор:

  • Если исключения не указаны явно в диалоговом окне "Отладка- > Исключения", а "Параметры → " Отладка "- > " Включить только мой код "(EJMC) не отмечены, то исключение, вызванное любым вызовом, не будет разрыв с первым исключением (FCE)

  • Если исключения не указаны явно в диалоговом окне "Отладка- > Исключения" и EJMC отмечен, исключение, вызванное обратным вызовом TCPListener, будет прерываться с FCE, но не будет прерываться с FCE в Socket Обратный вызов

    а. Исправленное исключение не будет прерываться с FCE в обратном вызове Socket, даже если вызывается блокировка TCPListener AcceptSocket() (поэтому нет обратного вызова для прослушивателя).

  • Если в Exceptions > отмечен System.InvalidOperationException (или System), то соответствующее исключение, вызванное любым обратным вызовом, будет прерываться с FCE, независимо от того, отмечен ли EJMC или нет.

  • Вышеупомянутое верно, являются ли обратные вызовы заданными как лямбда или в пользовательской пользовательской функции

Я не знаю, почему VS не прерывается с FCE в обратном вызове сокета, если исключение явно не проверено в Debug- > Exceptions (что делает обратный вызов сокета отличным от обратного вызова слушателя).