2012-05-21 15 views
2

我有一個異步套接字服務器。我遇到了一個問題,即有問題的客戶端和難以重現的網絡事件導致瘋狂的字節數[]被鎖定。由於所有處理客戶端的線程都是隱式的(我使用BeginAcceptClient,我使用回調而不是顯式實例化的線程),我不控制釘住過程。 「隱式線程」是指線程不是由我直接生成的,而是由託管我的應用程序的運行時生成的。取消固定.NET套接字服務器中自動固定的字節[]

無論如何,this後的回答顯示瞭如何取消固定對象。如果我繼續前進並自己固定字節[],是否可以重寫幕後鎖定,在清理期間執行BeginRead並取消鎖定?

謝謝。

回答

4

您鏈接到的帖子中的答案是完全錯誤的(我剛剛在那裏留下了評論)。只有當最後一個釘住手柄(更一般:因爲除GCHandles之外還有其他原因而釘住「原因」)被移除時,該對象才被解除鎖定。你不能強制取消固定。這將是非常不安全的。你可以使用安全的託管代碼來做不安全的事情,甚至是安全問題!

無論如何,嘗試防止鎖定物體是沒有意義的。即使這是可能的,但事實並非如此,你的過程會隨機崩潰!套接字依賴於鎖定正確性。它沒有理由不這樣做。

的解決方案是在別處:

  1. 創建應用程序啓動時的所有緩衝區因此,所有緩衝器都在存儲器中連續。使用緩衝池。
  2. 使用少量大緩衝區並將其分配給各個客戶端。

一個小方面說明:固定與您的想法不同。固定不是可以在對象上打開和關閉的標誌。當你固定一些東西時,一開始沒有什麼特別的事情發生。只有當GC運行時,GC纔會注意到有引用了它們所固定的特殊屬性。然後它防止對象被移動。

+1

太棒了,謝謝。 – kmarks2

1

我建議你不要專注於Pin/Unpin,而是從不同的AppDomain中完成所有套接字調用。然後,您可以在處於「閒置/安全」狀態時卸載並重新加載該AppDomain,以將其中的內存重置爲良好狀態。

+1

他可以做一個手動GC來清除所有未使用的緩衝區。關閉一個appdomain不會添加任何有關GC的新功能。 GC是流程全球化的。 – usr

+1

GC是流程全局的,但清除AppDomain將調用該域中項目的所有終結器;其中之一,希望可以在仍然持有緩衝區的GCHandle上調用Free。它取決於有問題的代碼,但它可以釋放GC在下一次掃描時收集的數組。 – GWLlosa

+1

你假設有處理泄漏。 BCL套接字的實現當然沒有,他也沒有做任何固定。無論如何,關閉appdomain會斷開套接字。 – usr