Веб-служба C # застревает в ожидании блокировки, не возвращает - PullRequest
1 голос
/ 15 июня 2010

У нас есть приложение C # (2.0), которое общается с нашим сервером (в java) через веб-службы.

В последнее время мы начали наблюдать следующее поведение (ТОЛЬКО) одного из наших лабораторных компьютеров (XP): Время от времени (каждые несколько дней) один из запросов веб-службы будет просто зависать, не будет возвращаться или истечет время ожидания.

Ниже приведена трассировка стека, в которой она, кажется, застряла.

Понятия не имею, что здесь происходит. Любой указатель будет очень полезен.

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, Boolean) 05ecf160 7a5b29cc System.Net.ConnectStream.Read (Byte [], Int32, Int32) 05ecf1a0 79473cab System.IO.StreamReader.ReadBuffer (Char [], Int32, Int32, Boolean 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 [])

Изменить:

После ответа Дэвида я снова увидел все темы и нашел сообщника для тупика:

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 ]

1 голос
/ 16 июня 2010

У вас почти наверняка тупик.Предположим, у вас есть поток A, который снимает блокировку с объекта 2, а затем ожидает разблокировки объекта 1.Поток A должен ждать, потому что поток B снял блокировку на объекте 1, прежде чем он разблокирует объект 2. Теперь поток A и поток B будут ждать вечно, потому что каждый ожидает другого, чтобы разблокировать что-либо.

Использованиеотладчик, который просматривает каждый поток в вашей программе и видит, какие два потока находятся в ожидании блокировки.Затем выясните, какие замки они ждут.Затем выясните, как переписать вашу программу, чтобы эти две блокировки никогда не снимались в порядке, несовместимом для двух потоков.

Помните, что для написания правильного кода блокировки требуется глобальное знание всех блокировок впрограмма, все операции со всеми потоками, которые могут их выводить в любом возможном порядке .Вот почему так трудно понять это правильно;большинство задач программирования требуют только местных знаний.Блокировки требуют глобального знания всей программы, включая части, которые вы не написали .Если какая-либо сторонняя dll снимает блокировку с объекта и ваш код ожидает этого же объекта, вы должны согласиться с этим сторонним кодом относительно правильного выбора порядка блокировки.

Это наиболеевероятная причина.Существует маловероятная, но возможная другая причина, которая заключается в том, что иногда вы прерываете поток между моментом, когда снята блокировка, и блоком наконец разблокировки выполняется.Это приведет к тупику в C # 3 и ниже;мы исправили генератор кода в C # 4, чтобы этого больше не происходило.Мораль этой истории здесь заключается не в том, чтобы «использовать C # 4», а в том, что «никогда не прерывайте поток и, в частности, не прерывайте поток, который может что-то блокировать».Прерывание потока должно использоваться только в качестве крайней меры, когда вы все равно останавливаете процесс.

1 голос
/ 15 июня 2010

Это выглядит связанным ... ошибка в CLR? Microsoft Connect

Редактировать : код в платформе 4.0 выглядит так, что блокировки обрабатываются совершенно по-разному. Возможно, это исправило ошибку.

...