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

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

Однако в следующем минимальном примере 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.

Ответы [ 3 ]

13 голосов
/ 30 мая 2012

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

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

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

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

13 голосов
/ 20 ноября 2011

Поскольку в настройках исключений вы видите только флажок «Брошено», я подозреваю, что в настройках отладки у вас включен «.Net Framework Source Stepping». Если вы включите «Просто мой код» (который отключает «.Net Framework Source Stepping»), вы должны установить флажки «User-Unhandled» и «Thrown» в диалоге настроек исключений, и вы также поймаете исключение в отладчике.

Screen Shot O 'Victory:

Screenshot showing the debugger halted at the exception as expected

1 голос
/ 26 мая 2012

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

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

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

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

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

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

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

...