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 (что делает обратный вызов сокета отличным от обратного вызова слушателя).