2010-10-26 24 views
3

首先,讓我解釋一下我的設置。我的服務器被設置作爲封送單獨的對象:.NET Remoting:如何處理斷開的對象

RemotingServices.Marshal(lsServer, ServerObject.objectUri); 

爲了具有從服務器到客戶端的雙向通信,所述客戶端激活ServerObject,然後傳遞在它自己的ClientObject(這也是一個MarshalByRefObject的)服務器使用ClientObject頂嘴到客戶端:

var lsClient = new ClientObject(); 

var lsServer = (ServerObject)Activator.GetObject(typeof(ServerObject), url); 
lsServer.attach(lsClient); 

附加方法被調用時,服務器將在列表中ClientObject並將其存儲:

public void attach(ClientObject client) { 
    clientList.Add(client); 
} 
然後

服務器可以調用名爲「SendMessage函數」的ClientObject的方法在其名單傳送到每個客戶端:

foreach(var c in clientList) { 
    c.SendMessage("Hello"); 
} 

,直到客戶遇到的是,已斷開的偉大工程。在這種情況下,客戶端拒絕連接會引發錯誤。我可以捕獲錯誤,但問題是我無法從服務器的列表中刪除對ClientObject的引用。下面再拋出「連接被拒絕」異常每當有客戶端已斷開:

clientList.Remove(badClient); 

那麼幾個問題:

1 - 有沒有一種方法可以檢測客戶端的連接狀態,而不必須捕捉錯誤?

2 - 當我做檢測已經斷開的客戶,爲什麼不從服務器的列表中刪除的對象的嘗試似乎「溝通」與客戶端(從而導致異常被再次拋出?)

編輯

帕特里克指出的下方,這樣做從列表中刪除原因列表遍歷我的對象,做對他們的比較(調用.Equals) - 這是什麼原因造成我的ClientObject試圖重新通訊並因此拋出異常。

爲了解決這個問題,我反而將列表更改爲一個字典,這個字典在連接到服務器時鎖定了由我的客戶端提供的唯一ID。然後,我使用該唯一ID來刪除客戶端。

我從來沒有找到直接的方式來確定客戶端是否斷開連接而不是捕獲錯誤。

回答

0

不能確定#2。但是,如果您嘗試從foreach循環中刪除clientList中的項目,則不能。這是一個.NET規則 - 枚舉時不改變可枚舉對象的內容。相反,如果你在foreach循環中發現錯誤,將它存儲在另一個列表(一個「斷開」列表)中。在foreach之後,從clientList中刪除所有斷開連接的項目。

+0

謝謝,實際上我並沒有在For循環中從列表中刪除它。這個錯誤是無法修改集合的東西。當我執行clientList.Remove(badClient)時,它拋出一個「拒絕連接」異常...這看起來很奇怪,但似乎通過引用「badClient」它試圖使用該對象與客戶端進行通信。 – bugfixr 2010-10-26 21:40:27

+0

什麼是clientList - 列表? Remove方法首先執行IndexOf以查看您傳入的對象是否實際存在於集合中。在封面之下,IndexOf可能會調用您的對象的Equals運算符,或者可能調用GetHashCode()。這些調用中的任何一個都會通過線路發送 - 從而導致額外的通信異常。 – PatrickSteele 2010-10-26 21:46:23

+0

是的,它是一個List - 然後纔有意義。 – bugfixr 2010-10-26 21:58:35