Як налагодити один потік у Visual Studio?


254

У мене є рішення з деякими проектами. У різних проектах є декілька перерв. Я хочу простежити, щоб перша нитка потрапила на одну з цих точок розриву і продовжувала відстежувати цей єдиний потік, незважаючи на те, що інші потоки вводять ті самі кодові блоки.

Я знаю, що це можливо через визначення умови точки прориву, тобто ім'я потоку = ... або потоку Id = ..., але мій випадок - це важко завантажений ASP.NET додаток, і як тільки я приєднаюся до w3wp.exeбагатьох нитки будуть вражати точки розриву. Мені потрібна така річ, як ThreadLocal<break-point>.

Це можливо? Якщо так, то як?


7
@ Paolo: Цей веб-додаток працює як серце великої веб-ферми, і ситуацію з глюками неможливо імітувати в сценаріях тестування.
Xaqron

Для VS 2019, можливо, варто спробувати це: stackoverflow.com/a/61868591/8579563
Gozo

Відповіді:


150

Нитки заморожування / відтавання - це неправильний спосіб, оскільки інші потоки не виконують жодного коду.

Найбільш правильний і корисний спосіб - це:

  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
У мене ця проблема була назавжди, і я можу поклястись, що на своїй останній роботі я знайшов налаштування, яке зробило візуальну студію такою, як затемнення, де ви будете дотримуватися теми, з якою працювали, але я не можу її знайти чи будь-яку посилання йому. Я починаю замислюватися, чи мріяв я про це.
Ст

7
-1 тому, що це дозволяє лише точки прориву, але фактично не налагоджувати: переходити / переходити не працювати таким чином для налагодження однієї нитки.
Серж Рогач

338

Ось що я зробив:

  1. Встановіть умовну точку перерви, яку я знав, що вдарить лише по нитці, яку я шукав.

  2. Після того, як точка розриву буде досягнута, і ви перейдете до потрібної нитки, у вікні Visual Studio Threads (під час налагодження, Налагодження -> Windows -> Нитки), Ctrl+ A(щоб вибрати всі теми), а потім Ctrl+ натисніть на нитку, на якій ви зараз перебуваєте. . У вас повинні бути вибрані всі потоки, крім тієї, яку ви хочете налагодити.

  3. Клацніть правою кнопкою миші та виберіть "Заморозити".

Тепер Visual Studio лише переступить через розморожену нитку. Здається, це робиться набагато повільніше, мабуть, тому, що він повинен прокручувати всі заморожені нитки, але це принесло певну розумність моїй багатопотоковому налагодженню.


1
Це не працює для мене в контексті, коли у мене є близько 8 завдань, які виконуються в різних потоках. Я заморожую всі інші потоки і "переходжу", але IDE на деякий час замерзає, а потім переходить на інший потік.
Meta-Knight

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

3
@ Meta-Knight Вам слід заморозити всі потоки, крім основної теми. Якщо ви зробите так, як IDE не буде заморожено
Олексій Жуковський

15

Щойно я випустив розширення Visual Studio 2010+, яке робить саме те, що ви шукаєте. І це безкоштовно :).

Презентація

Це розширення Visual Studio додає два ярлики та кнопки панелі інструментів, щоб дозволити розробникам легко зосередитись на одному потоці під час налагодження багатопотокових програм.

Це різко зменшує потребу вручну зайти у вікно "Нитки", щоб заморозити / розморозити всі потоки, окрім тієї, якої потрібно дотримуватися, і тому допомагає підвищити продуктивність.

Особливості

Обмежте подальше виконання лише поточним потоком. Заморозить усі інші потоки. Ярлик: CTRL + T + T або кнопка Сніжинка. Перехід до наступного єдиного потоку (на основі ID). Змінить поточну нитку та заморозить усі інші потоки. Ярлик: CTRL + T + J або Далі кнопка.

Перегляньте це тут, на Галереї , на офіційній сторінці або сховищі Github .


Яку версію VS ви використовуєте?
Ервін Майер

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

3
Я збираюся це перевірити. Ви, можливо, єдина людина на планеті, яка зробила будь-яку спробу вирішити одну з найбільших помилок налагодження у Microsoft.
Ст

на жаль, він не встановиться на vs2012. Чи є у вас новіша версія або ви хочете поділитися вихідним кодом, щоб я міг створити його сам?
Світ

@stu Вихідний код знаходиться на Codeplex тут: singlethread.codeplex.com він повинен працювати на VS 2012 та VS 2013, але я його не оновлював (ніхто не просив цього, і я не мав потреби в собі). Якщо ви можете змусити його легко працювати з VS 2012+ і взяти на себе зобов'язання над Codeplex, то я можу також натиснути його на Галерею.
Ервін Майєр

13

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

  • Встановіть точку розриву, щоб перервати потік у потрібній мені функції.
  • Як тільки нитка дістається до точки розриву і призупиняється, я видаляю точку розриву і продовжую налагоджувати за допомогою F8, F10 і F11, щоб інші потоки могли працювати.

Після того, як прочитав усі найвищі відповіді, цей спосіб спрацював для мене.
Swanand Pangam

9

Трохи інший підхід , який я використовував:

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

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


3
+1. "Це передбачає, що у вас є час ... перш ніж друга нитка потрапить на вашу точку розриву". Я загортаю крапку з комою в замок і ставлю крапку на крапку з комою. При першому попаданні точки відключення я відключаю точку зламу. Жодна інша нитка не може зайти через замок. lock(m_someObject) { ; }
блюдог

Щоб заощадити 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"

Можна також зробити те ж саме, отримавши "Керований ідентифікатор" потоку у вікні "Нитки" та скористайтеся:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.