问题
Normally, when the debugger is attached, Visual Studio 2010 stops at an unhandled exception even if the Exceptions dialog doesn’t have the tickmark for the exception type in the “Thrown” column. The keyword here is unhandled; said dialog refers only to handled exceptions.
However, in the following minimal example, Visual Studio 2010 does not stop at the exception for me, even though it appears in the Immediate Window as a first-chance exception:
EDIT: The first minimal example I posted was fixed by the first answer I received, but unfortunately the following example still exhibits the problem:
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();
}
}
}
If you run this, connect to it by running telnet localhost 8080
and then type any character into telnet, hopefully you will see what I see: the program just aborts silently.
Why does Visual Studio apparently swallow this exception? Can I get it to break at the exception as it usually does?
(Interestingly, throwing inside the BeginAcceptSocket
callback does get caught, as does an exception in a normal thread started with Thread.Start
. I can only reproduce the issue by throwing inside the BeginReceive
callback.)
回答1:
This is a known bug in CLR version 4. The feedback article is here. A possible workaround is to change the framework target to version 3.5. I'll just quote the relevant portion of the feedback response:
We have investigated the issue and determined there is a bug in CLR v4.0 which causes this. The process does throw the exception (you can catch it with a catch handler for example) but the debugger was not properly notified of the unhandled exception. This causes the process to appear to exit without any indication from the debugger about what happened. We have investigated potential fixes, however all of the fixes had moderate risk of breaking other functionality. Because it was very late in product cycle we decided it was safer not to fix this issue and risk creating new bugs. We will continue to track this issue as part of our next release cycle.
The issue is restricted to exceptions that escape managed code where the thread was created using a few specific API calls:
new System.Threading.Timer()
ThreadPool.UnsafeQueueNativeOverloapped
ThreadPool.BindHandle
ThreadPool.RegisterWaitForSingleObject.
It is RegisterWaitForSingleObject() in this specific case.
回答2:
Since you see only a 'Thrown' checkbox in the exception settings, my suspicion is that you have '.Net Framework Source Stepping' enabled in your debug settings. If you enable 'Just My Code' (which disables '.Net Framework Source Stepping'), you should get 'User-Unhandled' and 'Thrown' checkboxes in your exception settings dialog and you will also catch the exception in the debugger.
Screen Shot O' Victory:
回答3:
This is what I have discovered so far:
If no exceptions are explicitly checked in the Debug->Exceptions dialog and Options->Debugging->"Enable Just My Code" (EJMC) is not checked, then an exception thrown in any of the callbacks will not break with First Chance Exception (FCE)
If no exceptions are explicitly checked in the Debug->Exceptions dialog and EJMC is checked, then an exception thrown in the
TCPListener
's callback will break with FCE, but will not break with FCE in theSocket
's callbacka. An exception thrown will not break with FCE in the
Socket
's callback, even if theTCPListener
's blockingAcceptSocket()
is called (so no callback for listener).If
System.InvalidOperationException
(orSystem
) is checked in Debug->Exceptions, then an appropriate exception thrown in any of the callbacks will break with FCE, regardless of whether EJMC is checked or not.The above is true whether the callbacks are specified as lambda or in an excplicit user function
I do not know why VS does not break with FCE in the socket callback if the exception is not excplicitly checked in Debug->Exceptions (what makes the socket callback different from the listener callback).
来源:https://stackoverflow.com/questions/8197254/visual-studio-2010-doesn-t-stop-at-an-unhandled-exception-inside-a-socket-beginr