2012-12-03 44 views
1

我有一個類TCPDataLink使用Socket實現了一些TCP功能。我也有一個IOManager,它會在發生錯誤時執行一些日誌記錄(在我所有的DataLink上)。從事件中捕獲異常

問題是我找不到從我的IOManager類中找到Socket事件處理程序異常的方法。我不想在我的TCPDataLink類中注入Logger依賴關係,因爲我不想在我的所有DataLink類中重複日誌記錄代碼。

例如,在正常情況下:

// IOManager Class call in a normal case 
try 
{ 
    tcpInstance.DoSomething 
} 
catch (MyCustomEx e) 
{ 
    // Log the problem 
    Logger.log(e.ToString()); 
} 

在我的問題的情況下:

// TCPDataLink.cs 
... 
socket.OnConnection += ConnectionHandler // Cannot try/catch or whatever 
... 

void ConnectionHandler(...) 
{ 
    // Code throwing Exceptions 
} 

this螺紋,外的try/catch是不是一種選擇。所以我必須在我的ConnectionHanlder裏面抓到Exception ...?

什麼是我的IOManager記錄日誌的最佳選擇,無法趕上Exception

感謝,

回答

2

最好的辦法是趕上錯誤時拋出實際。用編排你的應用程序工作流預期的異常處理有時候你通常在IO交互中做的事情經常沒有其他方法來正確處理。

所以只要在ConnectionHandler內部處理一下try/catch/throw的序列。 可能是,一次捕捉不要拋出異常,但只是處理它

+0

是的,我已經處理了異常(在我的示例中未報告,我會更新我的帖子)。我的問題是在c#中「期望的異常處理」的最佳方法是什麼(換句話說,如何通知我的'ConnectionHandler'?我可以通過事件做到這一點,但由於事件繼承是一種痛苦,我希望存在其他解決方案。 –

+0

@NicolasVoron:可以改用狀態變量。 – Tigran

+0

您能詳細解釋一下嗎? –

0

事件通常不應允許任何不如CpuOnFireException嚴重的例外逃脫。如果一個事件表示一個可能成功或者不可能成功的動作,並且其失敗需要被傳遞給調用代碼,那麼事件處理程序應該捕獲所有不太嚴重的異常,並通過「event arguments」參數傳遞關於它們的信息。當然,這會在代碼提升事件的過程中產生一個義務,以檢查是否有任何異常發生;它也可能會在事件處理程序中創建一個義務來檢查以前的處理程序中的問題是否應該導致事件處理程序忽略當前事件。

雖然使用MulticastDelegate來處理事件訂閱可能看起來簡單易行,但處理MulticastDelegate的一部分時發生的異常將會導致其他部分被跳過;在很多情況下,讓一個事件被跳過可能會將可恢復的異常轉變爲不可恢復的異常(例如,如果更新通知得到,應該保持更新以便彼此匹配的兩個集合可能不同步跳過)。雖然可以將MulticastDelegate分解成方法指針和目標列表,但使用其他數據類型(如EventHandler<T>[])來容納事件列表並且不打擾任何多播委託者會更容易。

+0

有趣的,你能提供一個基於我的例子的示例代碼嗎 –

+0

@ NicolasVoron:如果你的連接對象的性質是這樣的,一切都將完美的工作,除非或直到發生什麼事情使得車輪脫落,在這一點上該對象可能永久無用,我會建議可能有一個'ConnectionFailureCause'屬性最初將是空的,但會在第一次出現問題時進行設置(所有後續嘗試做的事情g與對象應該立即引發異常,但可能不需要連接對象來記錄它們)。該對象可能包含一個例外,但應該... – supercat

+0

...還包括關於它被抓到的位置的上下文。 'Exception'對象報告throw *相對於catch *的位置,如果它被捕獲它的代碼進行分析,這是非常好的,但如果將它存儲以供在完全不同的上下文中運行的代碼進行分析。 – supercat