2011-10-09 18 views
9

Kelimeden yavaş bir bellek sızıntısı yaşayan bir uygulamaya sahibim.Asılı finalizer kuyruğunun nedenini nasıl bulabilirim?

ANTS Bellek Profilcisini Kullanma Sızan belleğin tümünün sonlandırıcı kuyruğunun GC kökü tarafından tutulduğunu görebiliyorum.

Neler olabileceğinden şüpheleniyorum, son hale getiricinin erişilebilir bir kilitle beklemede kalması kilitleniyor.

Sınıflarımızın hiçbiri kesin sonlandırıcıları uygulamaz, onları kural olarak kullanmayız, bu da kilidin bir sistem veya kütüphane sınıfı ile ilgili olabileceğini düşünmeme neden olur.

Ben Finalizer sıranın içeriğine bakmak için SOS.dll kullandım ve doğru yorumlamak ediyorsam o zaman sıranın baş aslında temsil ediyorsa emin oldum Ancak bir örnek System.Threading.Thread olmak ilk öğeyi bildiriyor Halihazırda atılan nesne veya atılacak bir sonraki nesne.

  • Nelerin tamamlandığını öğrenmek için kullanabileceğim herhangi bir numara var mı?
  • Sonlandırıcı iş parçacığının beklemesini kilitlemenin bir yolu var mı?
  • Sonlandırıcı iş parçacığının eylemlerini izlemek için herhangi bir hata ayıklama etkinleştirilebilir mi?
  • Başka neler bakabilirim? aşağıdaki gibi

Güncelleme

Finalizer parçacığının yığını görünür:

[email protected]() + 0x15 bytes 
[email protected]() + 0x15 bytes 
[email protected]() + 0x15 bytes  

[email protected]() + 0x43 bytes  
kernel32.dll!_WaitForSing[email protected]() + 0x12 bytes 
ole32.dll!GetToSTA() + 0x72 bytes 

ole32.dll!CRpcChannelBuffer::SwitchAptAndDispatchCall() - 0x1939 bytes 
ole32.dll!CRpcChannelBuffer::SendReceive2() + 0xa6 bytes  
ole32.dll!CAptRpcChnl::SendReceive() + 0x5b7 bytes 
ole32.dll!CCtxComChnl::SendReceive() - 0x14b97 bytes  
ole32.dll!NdrExtpProxySendReceive() + 0x43 bytes  
[email protected]@4() + 0xe bytes  
rpcrt4.dll!_NdrClientCall2() + 0x144 bytes 
[email protected]() + 0x7a bytes  
[email protected]() + 0xf bytes 

ole32.dll!CObjectContext::InternalContextCallback() - 0x511f bytes 
ole32.dll!CObjectContext::ContextCallback() + 0x8f bytes  
clr.dll!CtxEntry::EnterContext() + 0x119 bytes 

clr.dll!RCWCleanupList::ReleaseRCWListInCorrectCtx() + 0x2bb bytes 

clr.dll!RCWCleanupList::CleanupAllWrappers() - 0x20fb0 bytes  
clr.dll!SyncBlockCache::CleanupSyncBlocks() + 0x1ec6 bytes 
clr.dll!Thread::DoExtraWorkForFinalizer() + 0x411b5 bytes 

clr.dll!WKS::GCHeap::FinalizerThreadWorker() + 0x8b bytes 
clr.dll!Thread::DoExtraWorkForFinalizer() + 0xb6e76 bytes 
clr.dll!Thread::ShouldChangeAbortToUnload() - 0x5f8 bytes 
clr.dll!Thread::ShouldChangeAbortToUnload() - 0x53d bytes 
clr.dll!ManagedThreadBase_NoADTransition() + 0x35 bytes  
clr.dll!ManagedThreadBase::FinalizerBase() + 0xf bytes 
clr.dll!WKS::GCHeap::FinalizerThreadStart() + 0xfb bytes  
clr.dll!Thread::intermediateThreadProc() + 0x48 bytes 
[email protected]@12() + 0x12 bytes  
[email protected]() + 0x27 bytes  
[email protected]() + 0x1b bytes  
+1

Niçin kural olarak kural koyuculardan kaçınıyorsunuz? Tek kullanımlık modelin uygun şekilde uygulanması * sonlandırıcı gerektirir. – svick

+2

@svick - MSDN re'de bir not. IDisposable uygulanıyor "Bir sınıfın kendiliğinden yönetilmeyen kaynaklara sahip değilse, finalizer'ı tamamen bırakın" – chillitom

+1

@svick - chillitom doğrudur. [Framework Design Guidelines] [http://www.amazon.com/Framework-Design-Guidelines-Conventions-Libraries/dp/0321545613] 'dan alıntı yaparak: "Yardım ederseniz gerçekten bir finalizer yazmak istemezsiniz." – TrueWill

cevap

9

bir COM sunucusu ile ilgili bir sorun yaşıyorsanız bana görünüyor. Çağrı yığını, tek iş parçacıklı bir COM nesnesinde IUnknown :: Release() çağrısını yapmaya çalıştığını gösterir. ReleaseRCWListInCorrectCtx() çağrısı, onu kapatır, _NtUserPostMessage @ 16(), COM nesnesinin sahibi olan STA'ya isteği ileten çağrıdır. Tipik neden COM nesneleri oluşturuyor ve bir ileti döngüsü pompalamıyor. STA konuları için zor bir gereklilik. Onları ana UI iş parçacığı üzerinde oluşturarak ve onu engellemeden önlersiniz.

+1

spot açık, programın ana yöntemi, bir GUI modunu barındırmak için [STAThread] olarak işaretlendi ancak normalde bir windows hizmeti olarak çalışırdı. Son zamanlarda bir COM bileşeni tanıtılmış olmalı, muhtemelen bir Zamanlayıcı adayı. UI iş parçacığı olmadan tahmin ettiğiniz gibi, hizmetin sonleştiricisi yalnızca askıda kalıyor. – chillitom

+1

FYI, Ana iş parçacığınız Console.ReadLine gibi bir şey yapıyorsa, ancak iletileri pompalamak istiyorsanız, readline yapmak için yeni bir iş parçacığı hazırlayabilir ve daha sonra '.Join' 'inizi Main'inizden kullanabilirsiniz. iplik. Dahili bir Thread.Join 'bir STA iş parçacığı çağrıldığında, nesneleri kullanmasını sağlayan COM iletilerini pompalar. –

İlgili konular