2011-06-13 78 views
3

我有一個WCF服務託管在控制檯應用程序中。我有一個ChannelFactory來調用WCF的操作合同。WCF序列化和緩存

問題:每當我調用一個返回值的操作時,似乎返回的值在被序列化時被服務緩存到某個地方。

我正在通過Windows 7下的任務管理器檢查服務內存的使用情況。當我調用一個不返回內存的操作時,內存不會增加,但是當我調用一個返回數據的操作時,內存會增加,即使在數據返回給客戶端之後。

我的猜測是這是一個序列化緩存問題?!?

+1

嘗試運行一些內存分析並查看哪些對象保留在內存中。你使用顯式緩存還是靜態變量來保存數據? – oleksii 2011-06-13 13:24:05

回答

2

內存可能會保持增加,直到GC運行,這不會對應於數據返回給客戶端的時間。

您是否曾嘗試向服務方法添加斷點或某種排序以確保每個請求上都調用該方法?我不認爲WCF會自行緩存;至少,我從來沒有在我的應用程序中使用它。


編輯:

記憶將繼續使用,直到垃圾收集器運行。如果你的進程仍然有足夠的可用空間,那麼真的沒有理由讓GC運行。

根據MSDN:當 一個滿足下列條件爲真時http://msdn.microsoft.com/en-us/library/ee787088.aspx#conditions_for_a_garbage_collection

垃圾收集:

  • 該系統具有低的物理內存。

  • 託管堆 上的已分配對象使用的內存超過了可接受的閾值。 這意味着可接受的內存使用量的閾值在託管堆上超過了 。該 閾值連續調整爲 該過程運行。

  • GC.Collect方法被調用。在幾乎所有情況下,因爲 垃圾回收器連續運行,所以您沒有 來調用此方法。 此方法主要用於 獨特的情況和測試。

很可能你分配在堆中的對象,但他們沒有被GC'd因爲GC認爲沒有理由運行(還有堆中代開的空間,也沒有理由花時間清理出來)。然而,如果你可以反覆重複你的WCF調用,並最終得到一個內存不足異常,那麼這將表明你確實有一個引用被保存在某個地方的問題。在那種情況下,我會使用內存分析器來確定什麼被保存在什麼位置。


編輯#2:

參見本主題:C# Thread not releasing memory

+0

是的,我已經完成了你所提到的。每個請求都會調用該方法。每次記憶增加並永不釋放! – scatman 2011-06-13 13:38:02

+0

噢好吧,也許我誤解了你的問題。我以爲你的意思是一遍又一遍地向客戶端發送同樣的響應,就好像回覆被緩存並且方法不會重新運行一樣。我將編輯我的答案... – CodingWithSpike 2011-06-13 13:43:41

+0

您無法在操作中調用集合,因爲對象仍在使用中。 – 2011-06-13 13:54:56

3

這聽起來更像是垃圾收集器還沒有運行,因爲內存沒有被釋放。此外,當在控制檯應用程序中託管WCF服務時,GC以工作站模式運行,在這種情況下可能效率較低。

+0

GC應該在什麼時候運行?我有一個堆棧溢出異常,但仍然沒有運行GC。無論如何,我可以手動釋放內存嗎?或者打電話給GC? – scatman 2011-06-13 13:35:50

+1

@scatman - 如果你有一個StackOverflow異常,那麼你有一個完整的其他問題。這通常表明某種遞歸沒有完成,如下所示:'public void MethodA(){MethodB(); } public void MethodB(){MethodA(); }調用其中一個函數會導致無限循環,並且每當調用堆棧變得太深時都會發生StackOverflowException。 – CodingWithSpike 2011-06-13 13:52:53

+0

@scatman - 您可以通過調用'System.GC.Collect()'來手動指示GC運行,如下所示:http://msdn.microsoft.com/en-us/library/system.gc.collect.aspx但是,這可能不會幫助您的StackOverflowException。它可能有助於確定對象引用是否阻止垃圾回收。 – CodingWithSpike 2011-06-13 13:56:02

1

使用這樣的工具來查看正在創建/收集的對象: http://memprofiler.com/

我不會如果在每次調用之後沒有運行GC,那麼擔心得太多 - 無論如何,這不會非常有效 - 垃圾收集器將運行在.NET框架確定對象足夠大以便收集的時候。如果內存開始變低,則會更頻繁地發生。