hi,我搜索了有关永久阻止的终结器线程的各种帖子和答案。几个似乎有用,但我需要进一步说明。
在我的应用程序中,API调用是从Web服务到NT服务。我正在测试环境中工作,可以一遍又一遍地重现此“效果”。在我的测试中,我将遵循以下一般步骤:
我将遵循此常规过程,并更改测试以检查各种API调用,以查看这些API对应用程序的内存配置文件的作用。
在进行此操作时,我注意到偶尔停止负载测试时,会出现“线程被中止”异常。在客户环境的日志中也很少看到这种情况。进行API调用后,无论出于何种原因,客户端都将断开连接。
但是,在收到此异常之后,我注意到我的过程的终结器已挂起。 (NT类服务,而不是w3wp。)
无论该过程不负担多长时间,这都是!finalizequeue输出的顶部:
0:002> !finalizequeue
SyncBlocks to be cleaned up: 0
Free-Threaded Interfaces to be released: 0
MTA Interfaces to be released: 0
STA Interfaces to be released: 0
----------------------------------
generation 0 has 15 finalizable objects (0c4b3db8->0c4b3df4)
generation 1 has 9 finalizable objects (0c4b3d94->0c4b3db8)
generation 2 has 771 finalizable objects (0c4b3188->0c4b3d94)
Ready for finalization 178 objects (0c4b3df4->0c4b40bc)
我可以通过调用API来添加对象“ Ready For Finalization”,但是Finalizer线程似乎永远不会移动并清空列表。
上面显示的终结器线程是线程002。这是调用堆栈:
0:002> !clrstack
OS Thread Id: 0x29bc (2)
Child SP IP Call Site
03eaf790 77b4f29c [DebuggerU2MCatchHandlerFrame: 03eaf790]
0:002> kb 2000
# ChildEBP RetAddr Args to Child
00 03eae910 773a2080 00000001 03eaead8 00000001 ntdll!NtWaitForMultipleObjects+0xc
01 03eaeaa4 77047845 00000001 03eaead8 00000000 KERNELBASE!WaitForMultipleObjectsEx+0xf0
02 03eaeaf0 770475f5 05b72fb8 00000000 ffffffff combase!MTAThreadWaitForCall+0xd5 [d:\rs1\onecore\com\combase\dcomrem\channelb.cxx @ 7290]
03 03eaeb24 77018457 03eaee5c 042c15b8 05b72fb8 combase!MTAThreadDispatchCrossApartmentCall+0xb5 [d:\rs1\onecore\com\combase\dcomrem\chancont.cxx @ 227]
04 (Inline) -------- -------- -------- -------- combase!CSyncClientCall::SwitchAptAndDispatchCall+0x38a [d:\rs1\onecore\com\combase\dcomrem\channelb.cxx @ 6050]
05 03eaec40 76fbe16b 03eaee5c 03eaee34 03eaee5c combase!CSyncClientCall::SendReceive2+0x457 [d:\rs1\onecore\com\combase\dcomrem\channelb.cxx @ 5764]
06 (Inline) -------- -------- -------- -------- combase!SyncClientCallRetryContext::SendReceiveWithRetry+0x29 [d:\rs1\onecore\com\combase\dcomrem\callctrl.cxx @ 1734]
07 (Inline) -------- -------- -------- -------- combase!CSyncClientCall::SendReceiveInRetryContext+0x29 [d:\rs1\onecore\com\combase\dcomrem\callctrl.cxx @ 632]
08 03eaec9c 77017daa 05b72fb8 03eaee5c 03eaee34 combase!DefaultSendReceive+0x8b [d:\rs1\onecore\com\combase\dcomrem\callctrl.cxx @ 590]
09 03eaee10 76f72fa5 03eaee5c 03eaee34 03eaf3d0 combase!CSyncClientCall::SendReceive+0x68a [d:\rs1\onecore\com\combase\dcomrem\ctxchnl.cxx @ 767]
0a (Inline) -------- -------- -------- -------- combase!CClientChannel::SendReceive+0x7c [d:\rs1\onecore\com\combase\dcomrem\ctxchnl.cxx @ 702]
0b 03eaee3c 76e15eea 05b59e04 03eaef48 17147876 combase!NdrExtpProxySendReceive+0xd5 [d:\rs1\onecore\com\combase\ndr\ndrole\proxy.cxx @ 1965]
0c 03eaf358 76f73b30 76f5bd70 76f84096 03eaf390 rpcrt4!NdrClientCall2+0x53a
0d 03eaf378 7706313f 03eaf390 00000008 03eaf420 combase!ObjectStublessClient+0x70 [d:\rs1\onecore\com\combase\ndr\ndrole\i386\stblsclt.cxx @ 217]
0e 03eaf388 77026d85 05b59e04 03eaf3d0 011d0940 combase!ObjectStubless+0xf [d:\rs1\onecore\com\combase\ndr\ndrole\i386\stubless.asm @ 171]
0f 03eaf420 77026f30 011d0930 73b1a9e0 03eaf4e4 combase!CObjectContext::InternalContextCallback+0x255 [d:\rs1\onecore\com\combase\dcomrem\context.cxx @ 4401]
10 03eaf474 73b1a88b 011d0940 73b1a9e0 03eaf4e4 combase!CObjectContext::ContextCallback+0xc0 [d:\rs1\onecore\com\combase\dcomrem\context.cxx @ 4305]
11 03eaf574 73b1a962 73b689d0 03eaf60c b42b9326 clr!CtxEntry::EnterContext+0x252
12 03eaf5ac 73b1a9a3 73b689d0 03eaf60c 00000000 clr!RCW::EnterContext+0x3a
13 03eaf5d0 73b1eed3 03eaf60c b42b936a 740ecf60 clr!RCWCleanupList::ReleaseRCWListInCorrectCtx+0xbc
14 03eaf62c 73b6118f b42b90f6 03eaf790 00000000 clr!RCWCleanupList::CleanupAllWrappers+0x119
15 03eaf67c 73b61568 03eaf790 73b60f00 00000001 clr!SyncBlockCache::CleanupSyncBlocks+0xd0
16 03eaf68c 73b60fa9 b42b9012 03eaf790 73b60f00 clr!Thread::DoExtraWorkForFinalizer+0x75
17 03eaf6bc 73a7b4c9 03eaf7dc 011a6248 03eaf7dc clr!FinalizerThread::FinalizerThreadWorker+0xba
18 03eaf6d0 73a7b533 b42b91fe 03eaf7dc 00000000 clr!ManagedThreadBase_DispatchInner+0x71
19 03eaf774 73a7b600 b42b915a 73b7a760 73b60f00 clr!ManagedThreadBase_DispatchMiddle+0x7e
1a 03eaf7d0 73b7a758 00000001 00000000 011b3120 clr!ManagedThreadBase_DispatchOuter+0x5b
1b 03eaf7f8 73b7a81f b42b9ebe 73b7a760 00000000 clr!ManagedThreadBase::FinalizerBase+0x33
1c 03eaf834 73af15a1 00000000 00000000 00000000 clr!FinalizerThread::FinalizerThreadStart+0xd4
1d 03eaf8d0 753c62c4 011ae320 753c62a0 c455bdb0 clr!Thread::intermediateThreadProc+0x55
1e 03eaf8e4 77b41f69 011ae320 9d323ee5 00000000 kernel32!BaseThreadInitThunk+0x24
1f 03eaf92c 77b41f34 ffffffff 77b6361e 00000000 ntdll!__RtlUserThreadStart+0x2f
20 03eaf93c 00000000 73af1550 011ae320 00000000 ntdll!_RtlUserThreadStart+0x1b
通过重复几次,我得到了“线程被中止”异常的关联,并且每次都使用此调用堆栈获得了挂起的终结器。任何人都可以提供有关终结器正在等待什么的澄清,以及其他可能有助于确定解决方案的相关问题吗?
谢谢?随时问您是否需要更多信息。
编辑后的添加项如下: 在阅读了汉斯的分析报告后,我的主管向我发送了System.ComponentModel.Component的代码,我需要尝试对这一点进行澄清。 (即使我发送的代码某种程度上是错误的版本。)
以下是System.ComponentModel.Component的终结器:
~Component() {
Dispose(false);
}
这里是Dispose(布尔):
protected virtual void Dispose(bool disposing) {
if (disposing) {
lock(this) {
if (site != null && site.Container != null) {
site.Container.Remove(this);
}
if (events != null) {
EventHandler handler = (EventHandler)events[EventDisposed];
if (handler != null) handler(this, EventArgs.Empty);
}
}
}
}
希望我不会在这里犯一个愚蠢的错误,但是如果终结器线程仅调用Dispose(false),则它可能无法阻止任何内容。如果那是真的,那我是不是树错了树?我应该再找其他班吗?
如何使用转储文件确定终结器所挂在的实际对象类型?
第二次修改: 我运行了负载测试,并监视了最终生存者,直到我开始看到它上升。然后,我停止了负载测试。结果是即使我几次造成GC,最终幸存者也“卡在” 88,并且从未下降。我重置并重新启动了SQL Server,但该统计数据仍然停留在88。
我转储了该过程,并捕获了finalizequeue输出,虽然对此感到困惑,但我注意到perfmon在转储大约15分钟后突然注册了finalize幸存者。
我进行了另一个转储,并重新捕获了finalizequeue输出,并将其与前一个进行比较。大多数都相同,但有以下区别:
B A Diff
4 0 -4 System.Transactions.SafeIUnknown
6 0 -6 OurCompany.Xpedite.LogOutResponseContent
20 0 -20 System.Net.Sockets.OverlappedCache
8 2 -6 System.Security.SafeBSTRHandle
21 3 -18 System.Net.SafeNativeOverlapped
6 4 -2 Microsoft.Win32.SafeHandles.SafeFileHandle
8 9 1 System.Threading.ThreadPoolWorkQueueThreadLocals
19 1 -18 System.Net.Sockets.OverlappedAsyncResult
7 2 -5 System.Data.SqlClient.SqlDataAdapter
7 2 -5 System.Data.DataSet
13 7 -6 OurCompany.Services.Messaging.Message
79 13 -66 Microsoft.Win32.SafeHandles.SafeAccessTokenHandle
6 4 -2 System.IO.FileStream
24 3 -21 System.Data.SqlClient.SqlConnection
40 22 -18 Microsoft.Win32.SafeHandles.SafeWaitHandle
17 3 -14 System.Data.SqlClient.SqlCommand
14 4 -10 System.Data.DataColumn
7 2 -5 System.Data.DataTable
21 20 -1 System.Threading.Thread
73 68 -5 System.Threading.ReaderWriterLock