9

我們正在使用EWS託管API,它在給定時間間隔後輪詢MS Exchange以查找新郵件。每次調用投票調用(PullSubscription.GetEvents()) - 微軟API都無法正確處理NetworkStream,並導致內存按比例增加。這以前是discussed here,但從未解決。使用ANTS Profiler,我們能夠確定哪些對象在內存中不斷增長並隔離問題。如何強制無法取消對象的垃圾回收?

現在問題已經被隔離 - 是否有一種方法來處理在我們沒有參考的外部API中創建的NetworkStream? GC.Collect()似乎沒有處理它,因爲它仍然有一個活動的引用。我們可以做些什麼來清理懸掛參考?我們可以使用一些包裝來強制清理其bug問題的SDK嗎?

+0

我想知道 - 你能通過反射獲得參考嗎? –

+0

您能否請您在庫中找到孤兒NetworkStream的地方?我只是圍繞GetEventsMethod進行探測,但沒有找到NetworkStream。 –

+0

@HenningKrause我也給了Daren Thomas的方法一個嘗試,但反思需要深入研究我選擇跳過的ExchangeService和SubscriptionBase類的內部。目前我已經跟着Salvatore的#1現在開了一張MS的門票。我們將看到接下來會發生什麼... – SliverNinja

回答

6

無法強制GC爲引用對象釋放內存!

首先,我建議聯繫微軟本身尋求幫助解決這個問題。

其次,你是在談論「處置」還是隻是內存釋放?他們是兩個完全不同的東西。 (IDisposable模式,終結者)。

第三,你可以解引用引用這些對象的對象嗎?第四,一種可能的解決方案可以是用反射器反編譯給你的代碼,理解你可以到達保持引用對象的字段的方式,在你的代碼中使用反射來訪問私有字段並把它們設置爲null。 是一件非常骯髒的黑客,但如果你沒有別的辦法是我能想到的唯一的事情。只有在你不能以其他方式進入時才這樣做。

+0

即使該字段不是靜態的,你在4中的骯髒的黑客也會工作。假定有一些對象不應該是「未引用」的,但是(可能間接地)保持有問題的對象存活。 – svick

+0

是的,當然,這種方法適用於所有情況,但如果您只能解引用不是解除引用其他對象的對象,並且您可以這樣做,我當然會建議這樣做,而不會有任何骯髒的入侵。 –

0

最簡單的方法是運行將SDK連接到它自己的AppDomain並完成卸載AppDomain之後的部分。這將導致在AppDomain中分配的所有內存被釋放。

但你需要添加一些工作,你的項目,因爲你只能有AppDomain的一個MarshalByRef對象或標記爲serilizable互換。

這也將允許您監視AppDomain消耗的內存量。所以你可以創建你的AppDomain,在其中運行有問題的SDK,如果它達到了特殊的內存消耗限制,你可以卸載它。