簡體   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