我们有一个C#(2.0)应用程序,通过Web服务与我们的服务器(在java中)进行通信。
最近我们开始在(仅)我们的一台实验室机器(XP)中看到以下行为:
偶尔(每隔几天),其中一个webservice请求就会卡住,不会返回或超时。
以下是堆栈跟踪,它似乎卡住了。
不知道这里发生了什么。
任何指针都会有很大的帮助。
ESP EIP
05eceeec 7c90eb94 [GCFrame:05eceeec]
05ecefbc 7c90eb94 [HelperMethodFrame_1OBJ:05ecefbc]
System.Threading.Monitor.Enter(System.Object的)
05ecf014 7a5b0034
System.Net.ConnectionGroup.Disassociate(System.Net.Connection)
05ecf040 7a5aeaa7
System.Net.Connection.PrepareCloseConnectionSocket(System.Net.ConnectionReturnResult
为ByRef)
05ecf0a4 7a5ac0e1
System.Net.Connection.ReadStartNextRequest(System.Net.WebRequest,
System.Net.ConnectionReturnResult ByRef)
05ecf0e8 7a5b1119
System.Net.ConnectStream.CallDone(System.Net.ConnectionReturnResult)
05ecf0fc 7a5b3b5a System.Net.ConnectStream.ReadChunkedSync(Byte [],Int32,
INT32)
05ecf114 7a5b2b90 System.Net.ConnectStream.ReadWithoutValidation(Byte [],Int32,
Int32,布尔值)
05ecf160 7a5b29cc System.Net.ConnectStream.Read(Byte [],Int32,Int32)
05ecf1a0 79473cab System.IO.StreamReader.ReadBuffer(Char [],Int32,Int32,
布尔ByRef)
05ecf1c4 79473bd6 System.IO.StreamReader.Read(Char [],Int32,Int32)
05ecf1e8 69c29119 System.Xml.XmlTextReaderImpl.ReadData()
05ecf1f8 69c2ad70 System.Xml.XmlTextReaderImpl.ParseDocumentContent()
05ecf20c 69c292d7 System.Xml.XmlTextReaderImpl.Read()
05ecf21c 69c2929d System.Xml.XmlTextReader.Read()
05ecf220 6991b3e7
System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(System.Web.Services.Protocols.SoapClientMessage,
System.Net.WebResponse,System.IO.Stream,Boolean)
05ecf268 69919ed1
System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(System.String,
System.Object的[])
修改
在David的回答之后,我又看到了所有的线程,并找到了死锁的帮凶:
ESP EIP
11a2f6f0 7c90eb94 [GCFrame:11a2f6f0]
11a2f7c0 7c90eb94 [HelperMethodFrame_1OBJ:11a2f7c0] System.Threading.Monitor.Enter(System.Object)
11a2f818 7a5ae107 System.Net.Connection.CloseOnIdle()
11a2f844 7a5b0403 System.Net.ConnectionGroup.DisableKeepAliveOnConnections()
11a2f878 7a58c035 System.Net.ServicePoint.ReleaseAllConnectionGroups()
11a2f8b4 7a58d40a System.Net.ServicePointManager.IdleServicePointTimeoutCallback(Timer,Int32,System.Object)
11a2f8e8 7a5d2f40 System.Net.TimerThread + TimerNode.Fire()
11a2f928 7a5d2bb2 System.Net.TimerThread + TimerQueue.Fire(Int32 ByRef)
11a2f968 7a5d2540 System.Net.TimerThread.ThreadProc()
11a2f9b4 793d7a7b System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
11a2f9bc 793683dd System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,System.Threading.ContextCallback,System.Object)
11a2f9d4 793d7b5c System.Threading.ThreadHelper.ThreadStart()
11a2fbf8 79e88f63 [GCFrame:11a2fbf8]
那么,我们知道它是否在4.0中修复了吗?
2 个答案:
答案 0 :(得分:1)
这看起来与CLR中的相关...错误?
Microsoft Connect
编辑:4.0框架中的代码看起来像锁完全不同。它可能已经修复了这个错误。
答案 1 :(得分:1)
你几乎肯定会遇到僵局。假设您有线程A取出对象2上的锁,然后等待对象1解锁。线程A必须等待,因为线程B在解锁对象2之前已取出对象1上的锁。现在线程A和线程B将永远等待,因为每个线程都在等待另一个解锁某些东西。
使用调试器查看程序中的每个线程,看看哪两个线程都在那里等待锁定。然后找出他们正在等待的锁。然后弄清楚如何重写程序,以便这两个锁永远不会以两个线程上不一致的顺序被取出。
请记住,编写正确的锁定代码需要程序中所有锁的全局知识,所有线程上的所有操作都可能在每个可能的顺序中将它们取出。这就是为什么要做到这一点很难的原因;大多数编程任务只需要本地知识。锁需要全局了解整个程序,包括您未编写的部分。如果某个第三方dll正在对某个对象进行锁定并且您的代码正在等待同一个对象,那么您必须同意该第三方代码的正确锁定顺序选择。
这是最可能的原因。有一个不太可能但可能的其他原因,即有时您在取出锁定和解锁finally块执行之间中止线程。这将导致C#3及以下的僵局;我们已经在C#4中修复了代码生成器,因此不再发生这种情况。这里故事的寓意虽然不是“使用C#4”,但它“不会中止线程,特别是不要中止可能锁定某些东西的线程”。线程中止应该仅用作最后的手段,无论如何都要进行此过程。