2010-02-08 81 views
4

我公司爲GUI應用程序提供網絡組件(DLL)。爲什麼這個SocketException未被泛型catch例程捕獲?

它使用定時器來檢查斷開連接。如果要重新連接,它要求:

internal void timClock_TimerCallback(object state) 
{ 
    lock (someLock) 
    { 
    // ... 
    try 
    { 
     DoConnect(); 
    } 
    catch (Exception e) 
    { 
     // Log e.Message omitted 
     // Raise event with e as parameter 
     ErrorEvent(this, new ErrorEventArgs(e)); 
     DoDisconnect(); 
    } 
    // ... 
    } 
} 

所以,問題是,在DoConnect()例程SocketException拋出(而不是抓)的內部。我會假設catch(Exception e)應該捕獲所有的異常,但是不知何故SocketException並沒有被捕獲並且顯示給GUI應用程序。

protected void DoConnect() 
{ 
    // 
    client = new TcpClient(); 
    client.NoDelay = true; 
    // In the following call the SocketException is thrown 
    client.Connect(endPoint.Address.ToString(), endPoint.Port); 
    // ... (login stuff) 
} 

該文檔證實SocketException擴展了Exception。 是出現了堆棧跟蹤是:

TcpClient.Connect() -> DoConnect() -> timClock_TimerCallback 

所以沒有拋出異常的try/catch塊之外。

任何想法,爲什麼它不工作?

+0

只有在連接了調試器或始終運行代碼時纔會出現此問題嗎?此外catch還可以捕獲try塊中的所有異常 - 但是如果您的DoConnect執行了一次fire並忘記了該異常,則DoConnect將返回並且處理將繼續導致異常被您的預期處理程序取消處理。 – cfeduke 2010-02-08 15:42:13

回答

0

我寫了一個小程序,無法重現,一個SocketException被捕獲到TimerCallback中就好了。

所以我建議你重新考慮你的分析,問題可能不是你認爲的問題。幾點建議:

  • 在定時器外運行。 T帽子將線程從線程中取出。
  • 在調試器中運行它。異常真的發生在哪裏?
  • 逐步完成異常處理。 ErrorEvent正在做它應該做的事情嗎?
+0

謝謝,我問了這個問題,因爲我也沒有解釋爲什麼會發生這種情況,並希望獲得新的靈感。我不認爲它是可重現的(如你的程序所示),但它顯然發生了,所以我必須進行調查。 – Tarnschaf 2010-02-08 19:25:55

+0

該行爲仍然不可重現,因此我添加了調試代碼並將等待它再次發生。接受你的答案,因爲它是最直接的。 – Tarnschaf 2010-02-09 10:10:03

1

如果ErrorEvent確實會引發另一個異常(根據評論),那麼DoDisconnect()永遠不會執行。

否則,你看到的例外可能是未來的形式DoDisconnect()

+0

請參閱添加的堆棧跟蹤爲什麼這不能成爲解決方案 – Tarnschaf 2010-02-08 15:42:35

0

你能張貼DoConnect()代碼?

也可以嘗試: 你可以在DoConnect()中捕獲它嗎? 嘗試捕捉特定的異常,而不僅僅是泛型。 如果您使用調試模式,它會如何反應?

+0

讀取留給其他人的回覆,保持原樣,但添加一個SECOND catch塊來捕獲SocketExeption或Win32Exception。 – Roast 2010-02-08 15:43:31

+0

根據請求添加了DoConnect()方法。你是否也有解釋你的想法,因爲SocketException擴展了Win32Exception擴展了ExternalException extends Exception? – Tarnschaf 2010-02-08 15:46:03

+0

有兩個原因,.NET 1.1 win32exception不是從Exception派生的。否則,您的異常不會被捕獲,因爲它在DoConnect內啓動的另一個線程上引發。 – Roast 2010-02-08 15:55:01

0

您的timClock_TimerCallback不會在catch語句想要捕獲異常的同一線程中調用。您應該捕獲timClock_TimerCallback中的異常,然後調用一個調用自身的方法,然後在正確的線程中重新拋出異常。

不知道這會起作用,但你可以試試看。

+1

這聽起來很有趣..但是從TimerCallback線程調用TcpClient.Connect()在哪裏也捕獲駐留,其他線程可能涉及? – Tarnschaf 2010-02-08 15:56:59

+0

糟糕,我通過DoConnect調用了timClock_TimerCallback,但那顯然是錯誤的。恐怕我的回答不會幫助你。 – 2010-02-09 08:18:05

相關問題