ContextSwitchDeadlock виявлено помилку в C #


80

Я запускаю програму C #, і під час виконання я отримую таку помилку:

CLR не зміг перейти від контексту COM 0x20e480 до контексту COM 0x20e5f0 протягом 60 секунд. Потік, якому належить цільовий контекст / квартира, швидше за все, або робить неперекачувальне очікування, або обробляє дуже тривалу операцію без перекачування повідомлень Windows. Ця ситуація, як правило, негативно впливає на продуктивність і може навіть призвести до того, що програма не реагує, або використання пам’яті постійно накопичується з часом. Щоб уникнути цієї проблеми, усі потоки однопотокових квартир (STA) повинні використовувати примітиви очікування накачування (наприклад, CoWaitForMultipleHandles) і регулярно перекачувати повідомлення під час тривалих операцій.

Хто-небудь може допомогти мені вирішити проблему тут?

Дуже дякую.

Відповіді:


123

Основний потік вашої програми був зайнятий виконанням коду протягом хвилини. Він не дбає про свої звичайні обов'язки, прокачуючи цикл повідомлень. Це незаконно, коли ви використовуєте COM-сервери в робочому потоці: виклики їх методів не можуть бути відправлені, поки ваш основний потік знову не буде простоювати.

Це повинно бути добре видно, ваш інтерфейс користувача повинен бути мертвим, як цвях для дверей. Windows повинна була замінити ваше головне вікно привидом, який відображає "Не відповідає". Закриття вікна не спрацює, жодні події кліків не матимуть жодного ефекту.

Що б не робив ваш основний потік, замість цього повинен виконуватися робочий потік. BackgroundWorkerКлас хороший для цього, ви знайдете багато допомоги використання в статті MSDN Library для нього. Використовуйте Debug + Break All, Debug + Windows + Threads, якщо ви не уявляєте, що робить основний потік.

Ще одна можлива причина: не забудьте встановити пакет оновлень 1, якщо ви використовуєте RTM-версію VS2005.


5
+1 за пояснення того, що такий робочий елемент слід перемістити у вторинний потік, таким чином, рішення про те, як уникнути цієї помилки (а не просто про те, що її спричиняє).
JYelton,

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

Документація MSDN: contextSwitchDeadlock MDA msdn.microsoft.com/en-us/library/ms172233%28v=vs.110%29.aspx
D_Bester

1
Дякую за детальне пояснення. Обхідні шляхи, якими я користувався, - це функції асинхронізації, що тепер цілком логічно. Отже, з того, що я збираю, дуже важливо керувати новим потоком для тривалих операцій, особливо під час використання COM.
Ентоні Мейсон,

50

Щоб знайти, яка операція блокує перемикач контексту та викликає відображення контексту MDA contextSwitchDeadlock , можна виконати наступні кроки. Зауважте, що я буду мати на увазі Visual Studio 2012.

  1. Відтворіть помилку. Це може спричинити деякі спроби та помилки.
  2. Натисніть кнопку "ОК", а не "Продовжити" у вікні Помічника з керованої налагодження, яке відобразиться.
  3. Переконайтеся, що панель інструментів "Розташування налагодження" активна, клацнувши правою кнопкою миші на області стикування панелі інструментів і вибравши "Розташування налагодження". На панелі інструментів ви побачите випадаючий список із написом "Потік", якщо він активний.
  4. Вибраний елемент у розкривному списку Потік повинен бути потоком, відмінним від основного потоку, оскільки це буде фоновий потік, який скаржиться, що основний потік залучає всю увагу. Виберіть основний потік у випадаючому списку.
  5. Тепер ви повинні побачити код, який блокує перемикач контексту в редакторі коду.

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

У налагоджувачі Visual Studio

  1. Ви можете вимкнути MDA безпосередньо в діалоговому вікні MDA, яке відображається, коли виникає помилка, знявши прапорець біля пункту "Перервати при видаленні цього типу винятку".
  2. З діалоговим вікном Налаштування винятків, використовуючи інструкції нижче від MSDN .

... у меню Налагодження натисніть Винятки. (Якщо меню "Налагодження" не містить команди "Винятки", натисніть "Налаштувати" в меню "Інструменти", щоб додати її.) У діалоговому вікні "Винятки" розгорніть список Керовані помічники налагодження та зніміть прапорець "Викинути" для окремого MDA.

Поза налагоджувачем Visual Studio

  1. Ключ реєстру (широкоформатний, всі MDA)
  2. Змінна навколишнього середовища (можна встановити широку машину, MDA)
  3. Налаштування конфігурації програми (може бути вказано область застосування, MDA)

Примітка: Один із перших двох варіантів повинен мати значення 1, щоб третій мав ефект.

У моєму випадку проблемою став виклик ObjectContext.SaveChanges () в Entity Framework у консольному додатку. З MTAThreadAttribute застосовується до Main()методу виключення ContextSwitchDeadlock не було більше не піднято . На жаль, я не впевнений у повному впливі цієї зміни.


2
проголосуйте за чітке пояснення щодо пошуку коду, який блокує процес.
Гійом Шуерманс

10

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

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


4

У деяких випадках:
Налагодження -> Винятки -> Керовані помічники налагодження
та зняття позначки з пункту ContextSwitchDeadlock.


5
Так, але коли ви пишете разовий тест, і це вам заважає, приємно мати можливість його відключити.
Тод,

4
Ні. Неправильно. Це не вирішення проблеми.
Tom W

3
Треба думати як інженер, а не вчений !!
Ehsan Zargar Ershadi

4
@Ehsan Ershadi, хороший інженер передбачає та виправляє проблеми, а не штовхає його під килим!
Mo Patel

4
ЛОЛ. Якщо ви не хочете бачити помилку, ви можете просто шукати десь ще, крім монітора. Це такий самий підхід із вашим «рішенням». Це не рішення. Це просто ІГНОРУЄ!
цікаво Хлопець,

0

Просто виберіть Винятки з меню Налагодження у вікні Visual Studio 2005, відкриється діалогове вікно Edxception, виберіть Вузол винятків Керованих помічників для налагодження, потім виберіть ContextSwitchDeadlock і видаліть виділення зі стовпця Thrown. це зупинить vs від викидання винятку ContextSwitchDeadlock.

Сподіваюся, це допомагає ..


60
Ваша рука горить. Просто використовуйте ніж, щоб розрізати нерв, який посилає біль у ваш мозок. Це не дозволить вам помітити, що ваша рука горить.
Озза

У будь-якому випадку це спосіб тимчасового вирішення проблеми. Щоб повністю вирішити цю проблему, потрібно трохи часу, щоб переглянути проект програми.
Ван Цзицзюнь,

0

Я зіткнувся з цим питанням, коли намагався зрозуміти, чому мій OracleDataReaderкидає виняток. Я думав, що це тому, що він отримував призначення, nullоскільки виняток був пов'язаний з параметром, який був `null. Так я і зробив:

while (dr.Read())
{
    while (dr != null)  // <-- added this line
    {
      ...

Виявилося, що drНІКОЛИ не було нульовим, і тому цикл просто продовжувався і продовжувався, доки не прийшло це повідомлення, і ще і ще, тому що ви можете натиснути "Продовжити", щоб продовжувати це робити, поки не закінчиться пам'ять (не робіть цього - натисніть замість цього "OK"). Тож морально, шукайте витоків пам’яті, які передають дані з бази даних у пам’ять циклами до нескінченності. Помилка насправді намагається попередити вас про поганий сценарій. Найкраще прислухатися.


0

Ця помилка неодноразово виникла у мене, і я простежив її до ітерації DataGridViewRow, в якій встановив значення прапорця в значення true. Оскільки я працював у режимі налагодження, у мене була можливість продовжити, тож я зміг зробити саме це.

Сподіваюся, це комусь допомагає.


0

Припускаючи, що ви використовуєте Visual Studio, ви можете натиснути Ctrl+Alt+Eна поточному проекті, і відобразиться вікно винятків із вибраними Помічниками керованих налагоджень, вам слід зняти прапорець "ContextSwitchDeadlock". потім побудуйте поточний проект.

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