Как отладить тупик, когда в Visual Studio отображается только один поток? - PullRequest
0 голосов
/ 11 апреля 2011

Мое приложение блокируется на неопределенный срок при вызове lock ( obj ), но в окне потоков нет других потоков, у которых вообще есть какой-либо код для просмотра. Разве это не нужно для того, чтобы была вовлечена другая нить? Почему он не появляется, и что может быть причиной его отсутствия?

Обновление: Думаю, я понял, что это вызвало. У меня был такой хакерский блок, при котором я бы Wait() на ManualResetEvent внутри двух замков. Проблема была в том, что мне нужно было снять эти блокировки перед ожиданием, чтобы другие потоки могли их использовать, поэтому я делал что-то вроде этого:

lock ( one ) {
    lock ( two ) {
        ...
        Monitor.Exit( two );
        Monitor.Exit( one );
        syncEvent.Wait();
        Monitor.Enter( one );
        Monitor.Enter( two );
    }
}

На что я не рассчитывал, так это на то, что Monitor.Exit() на самом деле уменьшает только внутренний счетчик рекурсии, и, возможно, метод вызывался из блока, который уже был синхронизирован; таким образом, замок на самом деле не был освобожден .

Я думаю, это была плохая идея для начала. С тех пор я только что переместил вызов на Wait() за пределы заблокированных блоков, и теперь он, кажется, работает нормально.

Спасибо за понимание.

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

Ответы [ 2 ]

6 голосов
/ 11 апреля 2011

нет никаких других потоков в окне потоков, у которых есть какой-либо код для просмотра вообще

Уверяю вас, что эти другие потоки выполняют код.Есть ли у вас исходный код на вашем компьютере или нет, для этих потоков это не имеет значения.

Разве не обязательно, чтобы там был задействован другой поток?

Да.

Почему он не появляется, и что может быть причиной того, что он не отображается?

Возможно, поток, который снял блокировку, перешел в спящий режим,Это грубо - взять замок, а потом спать, не открывая его, но, безусловно, возможно.Или, может быть, один из тех потоков, который выполняет код, у которого нет исходного кода, чтобы снять блокировку.Например, предположим, что поток финализатора снял блокировку при финализации объекта, а затем поток финализатора завершил свою текущую партию работы.Опять же, грубо и глупо блокировать объект во время финализации, а затем не разблокировать его, но это, безусловно, возможно.

Существует миллион возможностей;Вы не дали нам достаточно информации, чтобы делать что-либо, кроме случайных предположений.Мой совет: постройте маленькое репро, которое наглядно демонстрирует проблему.При этом вы либо сами поймете, в чем проблема, либо у вас будет что-то конкретное, что мы можем обсудить, а не просто угадывать факты.

3 голосов
/ 11 апреля 2011

Хороший способ отладки - это запустить вашу программу через Concurrency Profiler в Visual Studio 2010. (однако, она доступна только для более мощных SKU). Она включает в себя множество инструментов для выделения и исследования взаимоблокировок и имеет тенденцию к работать лучше во многих сценариях, чем отладчик.

...