Как узнать, где произошла блокировка потока? - PullRequest
7 голосов
/ 12 июня 2010

У одного из приложений нашей компании Windows Forms была странная проблема в течение нескольких месяцев.Приложение работало очень надежно для большинства наших клиентов, но на некоторых ПК (в основном с беспроводным сетевым подключением) приложение иногда просто не отвечало.(Вы нажимаете на пользовательский интерфейс, и окна просят вас подождать или убить приложение).

Я долго не мог отследить проблему, но теперь я выяснил, что произошло.Приложение содержало следующую строчку кода

// don't blame me for this. Wasn't my code :D
Control.CheckForIllegalCrossThreadCalls = false

и использовало некоторые фоновые потоки для изменения элементов управления.

Нет, я нашел способ воспроизвести ошибку остановки приложения на моем компьютере разработчика и отслеживалвплоть до строки, где я фактически использовал Invoke () для запуска задачи в главном потоке.

Me.Invoke(MyDelegate, arg1, arg2)

Очевидно, что где-то была блокировка потока.После удаления оператора

Control.CheckForIllegalCrossThreadCalls = false

и рефакторинга всей программы для использования Invoke () при изменении элемента управления из фонового потока проблема (надеюсь) исчезла.

Однако яинтересно, есть ли способ найти такие ошибки, не отлаживая каждую строку кода (даже если я перестал работать в отладчике после того, как приложение перестало отвечать, я не могу сказать, что произошло последним, потому что среда IDE не перепрыгнула на оператор Invoke ())

Другими словами:

Если мои приложения зависают, как я могу определить, какая строка кода выполнялась последней?

Может быть, даже наПК для клиентов.

Я знаю, что VS2010 предлагает некоторую функцию обратной отладки, возможно, это было бы решением, но в настоящее время я использую VS2008.

Ответы [ 3 ]

2 голосов
/ 12 июня 2010

Возможно, это может помочь вам: http://www.debuginspector.com/index.htm

Это расширение Visual Studio, которое позволяет отслеживать взаимоблокировки и имеет множество других полезных функций для отладки потоков (например, просмотр стека вызовов нескольких потоков без перехода в окно потоков).

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

Вы, скорее всего, правильно определили виновника, установив для CheckForIllegalCrossThreadCalls значение false, это отличный способ создать случайный тупик.Единственная причина, по которой свойство существует, - это разрешить отладку подпрограмм .NET 1.x.

Для устранения тупиков, вам нужно использовать окно Debug + Windows + Threads для переключения между различными потоками и просмотрана их стеки вызовов.Но, учитывая вероятную природу источника, это будет сложно, так как это скорее всего неуправляемый код, который делает что-то с очередью сообщений или SendMessage ().Код, который вы не написали и для которого нет исходного кода или символов отладки.Они также имеют тенденцию быть случайными, в следующий раз они могут выглядеть совершенно по-другому.

Windows - это принципиально небезопасные объекты.У них очень большое количество состояния, связанного с ними.Не только в оболочках класса Windows Forms, но и в самой Windows.Я надеюсь, что вы исправили проблему.

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

Есть алгоритм для нахождения тупиков.Посмотрите на эти результаты Google: http://www.google.be/search?hl=en&client=safari&rls=en&q=deadlock+detection+algorithm&revid=1345706645&sa=X&ei=zqsSTPbmJ4qy0gTvtOWFCg&ved=0CD4Q1QIoAA

...