2011-05-03 75 views
5

我已經編寫了一個.Net(2.0)Windows服務,用於向用戶發送傳呼消息(通過串行端口連接到第三方硬件)。.Net 2.0 Windows服務在垃圾收集期間掛起

該服務定期查詢數據庫(OSI PI Historian),解析這些值並決定是否發送基於已更新值的消息。

該服務使用查找對象(其值來自SQL Server數據庫並每分鐘刷新一次)獲取用戶地址值和要發送的消息字符串。

該服務使用多個Threading.Timers來觸發定期的數據庫調用和消息發送。

服務安裝在安裝了.Net 2 SP2的Windows 2003計算機上。

該服務工作正常約一個星期,然後掛起。日誌(log4net)中沒有記錄異常。

我必須採取一些堆放的從服務器,他們都表現出相同的特點 - 線程觸發GC而無限期掛起

06aaf06c 7c827b99 77e61d1e 00004acc 00000000 ntdll!KiFastSystemCallRet 
06aaf070 77e61d1e 00004acc 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc 
06aaf0e0 79e8c5f9 00004acc ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xac 
06aaf124 79e8c52f 00004acc ffffffff 00000000 mscorwks!PEImage::LoadImage+0x1af 
06aaf174 79e8c54e ffffffff 00000000 00000000 mscorwks!CLREvent::WaitEx+0x117 
06aaf188 79f2f88f ffffffff 00000000 00000000 mscorwks!CLREvent::Wait+0x17 
06aaf1a8 79f2f8ca 7a3b9020 00000000 ffffffff mscorwks!SVR::gc_heap::user_thread_wait+0x50 
06aaf1b8 79f2f806 00000000 7a3b8b18 00080101 mscorwks!WKS::gc_heap::wait_to_proceed+0xe 
06aaf1cc 79f92f5a 00000000 00000000 00000000 mscorwks!WKS::gc_heap::garbage_collect+0x247 
06aaf1f8 79f94e26 00000000 00000000 00000030 mscorwks!WKS::GCHeap::GarbageCollectGeneration+0x1a9 
06aaf284 79f926ce 052c75c8 00000030 00000000 mscorwks!WKS::gc_heap::try_allocate_more_space+0x15b 
06aaf298 79f92769 052c75c8 00000030 00000000 mscorwks!WKS::gc_heap::allocate_more_space+0x11 
06aaf2b8 79e73291 052c75c8 0000002e 00000000 mscorwks!WKS::GCHeap::Alloc+0x3b 
06aaf2d4 79e7d8d4 0000002e 00000000 00000000 mscorwks!Alloc+0x60 
06aaf310 79e99056 0000000f b456b75e 00001ce3 mscorwks!SlowAllocateString+0x29 
06aaf3b4 792bb2c1 00000000 0108082b 00001f40 mscorwks!FramedAllocateString+0xa1 
    Stack shortened for bravity... 

管理堆棧:

ESP  EIP  
06aaf364 7c82847c [HelperMethodFrame: 06aaf364] 
06aaf3bc 792bb2c1 System.String.CreateStringFromEncoding(Byte*, Int32, System.Text.Encoding) 
06aaf3dc 792aaf2a System.Text.EncodingNLS.GetString(Byte[], Int32, Int32) 
06aaf3fc 6522d131 System.Data.SqlClient.TdsParserStateObject.ReadStringWithEncoding(Int32, System.Text.Encoding, Boolean) 
06aaf41c 656ca93e System.Data.SqlClient.TdsParser.ReadSqlStringValue(System.Data.SqlClient.SqlBuffer, Byte, Int32, System.Text.Encoding, Boolean, System.Data.SqlClient.TdsParserStateObject) 
06aaf448 6522d925 System.Data.SqlClient.TdsParser.ReadSqlValue(System.Data.SqlClient.SqlBuffer, System.Data.SqlClient.SqlMetaDataPriv, Int32, System.Data.SqlClient.TdsParserStateObject) 
06aaf474 656208b7 System.Data.SqlClient.SqlDataReader.ReadColumnData() 
06aaf484 65620962 System.Data.SqlClient.SqlDataReader.ReadColumn(Int32, Boolean) 
06aaf4b4 65221415 System.Data.SqlClient.SqlDataReader.GetValueInternal(Int32) 
06aaf4c8 652213af System.Data.SqlClient.SqlDataReader.GetValue(Int32) 
06aaf4f8 65220aec System.Data.SqlClient.SqlDataReader.get_Item(System.String) 
06aaf504 03616b81 AlarmEventCollator.DataAccess.GetAllAlarmDetails() 
06aaf564 03616a28 AlarmEventCollator.AlarmBuilder.buildLookups() 
06aaf590 0361aa89 AlarmEventCollator.AlarmBuilder.pollLookups(System.Object) 
06aaf5d0 792a83ff System.Threading._TimerCallback.TimerCallback_Context(System.Object) 
06aaf5d8 792e019f System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) 
06aaf5f0 792a836b System.Threading._TimerCallback.PerformTimerCallback(System.Object) 
06aaf77c 79e71b4c [GCFrame: 06aaf77c] 

的GC通常發生在數據庫解析方法中。所有其他託管線程似乎掛起 - 這將與GC進程一致。

我將不勝感激任何指針。根據要求提供更多信息。

+0

你正在處理很多不同的連接(SQL和串行)。 GC是否能夠收集所有舊的項目,或者是否存儲在內存中會導致內存使用量增加(靜態類或串行連接可能導致此問題,如果您不小心)?你有沒有看過內存使用,以確保它不像GC那樣簡單,因爲內存太滿(愚蠢的問題,我知道,但我不得不問)? – IAmTimCorey 2011-05-03 16:50:30

+1

另外,確保您在完成所有實現IDisposable的對象後立即處置它們。 – 2011-05-03 16:59:40

+0

我不相信內存中有任何過多的大對象 - 崩潰轉儲報告GC堆大小爲22mb。據我所知,所有可處置的物體都被丟棄。 – 2011-05-03 18:40:18

回答

2

在運行雙核機器上的服務器版GC的.NET進程中,我們有多少個GC線程?

兩個,每個處理器一個,或者說每個邏輯處理器一個,所以如果它是超線程的話它應該是4。在運行GC的工作站版本的進程中,我們不會有專用的GC線程,而是在啓動GC的線程上運行垃圾回收,因爲當您只有一個proc/one時,切換到垃圾回收的不同線程沒有意義線程正在執行GC。

Chris Lyon對GC模式進行了很好的寫作,也是一個關於Orcas中GC延遲模式的有趣帖子。

爲什麼這對你很重要?由於不同的GC模式針對不同的事情進行了優化,因此您的內存使用情況,GC延遲時間等可能會因您使用的GC模式而異。例如,默認情況下,Windows服務會獲取工作站GC,但是如果存在大量吞吐量(大量短期分配),則可能會更好地運行服務器GC以獲取內存使用情況和性能。

+0

是的,我通過將GC模式設置爲Server來解決了此問題。由於某些原因,GC在工作站模式下出現了性能/可靠性問題。 – 2011-08-22 12:12:31

+0

如果解決了這個問題,那麼您可以將其標記爲答案並關閉它。 – Ramprasad 2011-09-08 18:27:01