Как отладить один поток в Visual Studio?


254

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

Я знаю, что это возможно через определение условия на точке останова, то есть, имя потока = ... или идентификатор потока = ... но в моем случае это приложение ASP.NET с высокой нагрузкой, и как только я присоединяюсь ко w3wp.exeмногим темы будут бить точки останова. Мне нужно что - то типа ThreadLocal<break-point>.

Является ли это возможным? Если да, то как?


7
@Paolo: это веб-приложение работает как сердце большой веб-фермы, и в сценариях тестирования невозможно воспроизвести ситуацию с ошибками.
Xaqron

Для VS 2019, возможно, вы должны попробовать это: stackoverflow.com/a/61868591/8579563
Гозо

Ответы:


151

Замораживание / оттаивание потоков - неправильный способ, потому что другие потоки не выполняют никакого кода.

Самый правильный и удобный способ:

  1. Нажмите Ctrl + A в окне точек останова (выберите все точки останова).
  2. Щелкните правой кнопкой мыши и выберите «Фильтр ...».
  3. Введите "ThreadId = (текущий идентификатор потока)".

В Visual Studio 2015 и новее процесс аналогичен:

  1. Нажмите Ctrl + A в окне точек останова (выберите все точки останова).
  2. Щелкните правой кнопкой мыши и выберите «Настройки ...».
  3. Проверьте «Условия» и выберите «Фильтр» в раскрывающемся списке.
  4. Введите "ThreadId = (текущий идентификатор потока)".

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


51
Это мешает команде "Step" отладчика войти в другие потоки? Это была большая проблема, которая у меня была. Я перехожу через свою нить и вдруг оказываюсь в совершенно не связанной части кода. Я больше не занимаюсь разработкой в ​​Visual Studio, поэтому не могу тестировать.
Мэтт Фаус

8
Правый щелчок в окне точек останова не имеет команды «фильтр» ... и как вы узнаете текущий идентификатор потока? - Собираетесь ли вы в ближайшее окно и System.Threading.Thread.CurrentThread.ManagedThreadIdчто-то печатаете ?
BrainSlugs83

5
В моем VS (2015, Community Edition) невозможно изменить настройки нескольких точек останова одновременно. Таким образом, фильтр может быть установлен только один за другим.
robert4

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

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

338

Вот что я сделал:

  1. Установите условную точку останова, которая, как я знал, будет попадать только в поток, который я искал.

  2. Как только достигнута точка останова, и вы попадаете в нужный поток, в окне Потоки Visual Studio (при отладке, Отладка -> Windows -> Потоки), Ctrl+ A(чтобы выбрать все потоки), а затем Ctrl+ щелкните по потоку, в котором вы находитесь в данный момент. , Вы должны выбрать все потоки, кроме той, которую хотите отлаживать.

  3. Щелкните правой кнопкой мыши и выберите «Заморозить».

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


1
Это не работает для меня в контексте, где у меня есть около 8 задач, выполняющихся в разных потоках. Я замораживаю все остальные потоки и "перехожу", но IDE на некоторое время зависает, а затем в любом случае переходит на другой поток.
Мета-Рыцарь

3
@Diego: Я больше не работаю над проектом, но если он собирается заморозить все потоки, кроме одного, он изменит сценарий, вызвавший ошибку, так как потоки были дополняющими в ситуации с ошибками. Хотя это элегантное решение, похоже, эта функция должна быть встроена в VS.
Xaqron

3
@ Meta-Knight Вы должны заморозить все темы, кроме основной. Если вы так поступите, IDE не замерзнет
Алексей Жуковский

15

Я только что выпустил расширение Visual Studio 2010+, которое делает именно то, что вы ищете. И это бесплатно :).

презентация

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

Это значительно снижает необходимость вручную заходить в окно «Потоки», чтобы заморозить / разморозить все потоки, кроме того, которое необходимо соблюдать, и, следовательно, помогает повысить производительность.

Характеристики

Ограничить дальнейшее выполнение только текущим потоком. Заморозит все остальные темы. Сочетание клавиш: CTRL + T + T или кнопка Снежинка. Перейти к следующему отдельному потоку (на основе идентификатора). Изменит текущую тему и заморозит все остальные темы. Сочетание клавиш: CTRL + T + J или кнопка «Далее».

Проверьте это здесь, в Галерее , на официальной странице или в репозитории Github .


Какую версию VS вы используете?
Эрвин Майер

Я установил расширение, но не смог заставить его работать (для моего текущего проекта я использую VS2010). [Между прочим, то, что я считал проблемой с активацией потоков, просто происходит, когда потоки создаются, это, вероятно, стандартное поведение, поэтому я удалил свой предыдущий комментарий].
Вип

3
Я собираюсь проверить это. Вы можете быть единственным человеком на планете, который пытался решить одну из самых больших ошибок отладки в Microsoft.
Stu

увы, он не будет установлен на vs2012. У вас есть более новая версия или вы захотите поделиться исходным кодом, чтобы я мог собрать его сам?
Stu

@stu Исходный код находится на Codeplex здесь: singlethread.codeplex.com он должен работать на VS 2012 и VS 2013, но я не обновил его (никто не просил об этом, и я сам не нуждался в этом). Если вы можете легко заставить его работать с VS 2012+ и сделать коммит на Codeplex, то я могу также добавить его в Галерею.
Эрвин Майер

13

Если несколько потоков создаются как для веб-приложения, ответ @MattFaus не будет работать. вместо этого я сделал следующее

  • Установите точку останова для прерывания потока в функции, которую я хочу.
  • Как только поток достигает точки останова и ставится на паузу, я удаляю точку останова и продолжаю отладку, используя F8, F10 и F11, чтобы другие потоки могли работать.

После прочтения всех главных ответов этот обходной путь сработал для меня.
Суонанд Пангам

9

Немного другой подход , который я использовал:

  1. Создайте нормальную точку останова и дайте ей попасть
  2. Посмотрите в окне своих потоков идентификатор управляемого потока, который вы используете для текущей отладки.
  3. Щелкните правой кнопкой мыши точку останова в окне точек останова и выберите фильтр
  4. Введите ThreadId = xxx, где xxx - идентификатор потока из 2
  5. Теперь вы можете отлаживать, не останавливая другие потоки и не затрагивая вашу точку останова

Это предполагает, что у вас есть время сделать выше, прежде чем второй поток достигнет вашей точки останова. Если нет, и другие потоки достигли вашей точки останова, прежде чем вы сделали выше, вы можете щелкнуть по ним правой кнопкой мыши в окне потоков и выбрать остановку.


3
+1. Msgstr "Это предполагает, что у вас есть время ... прежде чем второй поток достигнет вашей точки останова". Я заворачиваю точку с запятой в замок и ставлю точку останова на точку с запятой. Когда точка останова попадает в первый раз, я отключаю точку останова. Никакие другие потоки не могут войти из-за блокировки. lock(m_someObject) { ; }
Bluedog

Чтобы сохранить вас в Google, окно потоков находится в разделе «Отладка»> «Windows»> «Потоки».
Гейб

2

В VS 2019:

  1. Установите точку останова где-нибудь.
  2. Хит F5 (Продолжить), пока ваша нить не приходит.
  3. Нажмите на точку останова, чтобы удалить ее.
  4. Вы можете перейти нить с помощью F10 или F11.

Работает и для VS2015!
доисторический

1

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

Однако, если это абсолютно необходимо и вам нужна статистика решения, я уверен, что вы могли бы добавить точку останова, которая прерывается, только если запрос приходит с вашего IP-адреса. Это можно сделать, добавив условную точку останова, которая проверяет HttpContext.Request.UserHostAddress. Обратите внимание, что это значительно замедляет ваше приложение.


Вот что я попробовал. Проблема в том, что этот экземпляр не работает в одном и том же домене (работает на IP или другом домене), и это приводит ко многим проблемам с сертификатами (SSL, WCF, ...), а также при низкой нагрузке ситуация с ошибками никогда не возникает!
Xaqron

Извините, я не уверен, что из этого вы пробовали, вы пробовали условную точку останова?
Steinar

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

1

Если вы не хотите останавливать все остальные потоки (возможно, вы подключаете отладчик Visual Studio к работающему приложению, которое должно отвечать на запросы), вы можете использовать макрос, который автоматически создает и удаляет точки останова.

Это предлагается в ответе на вопрос переполнения стека «Перешагнуть» при отладке многопоточных программ в Visual Studio .

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


1

Я думаю, что это немного отличается в Visual Studio 2015. Они изменили несколько вещей в точках останова, но вот как применить принятый ответ от hzdbyte (выше):

На точке останова в поле кодирования щелкните правой кнопкой мыши> Условия> Изменить с «Условное выражение» на «Фильтр». Это тогда позволяет вам фильтровать по ThreadId.

В качестве альтернативы в точке останова в окне «Точки останова» щелкните правой кнопкой мыши> «Настройки»> установите флажок «Условия» и выполните указанные выше действия.


1

Установите условие точки останова, щелкнув правой кнопкой мыши на боковой панели линии. Выберите «Условие» и введите следующее с названием вашей темы в кавычках:

System.Threading.Thread.CurrentThread.Name == "name_of_your_thread"

В качестве альтернативы вы можете сделать то же самое, получив «Управляемый ID» потока из окна «Threads» и используя:

System.Threading.Thread.CurrentThread.ManagedThreadId == your_managed_thread_id

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.