Ошибка ContextSwitchDeadlock была обнаружена в С#

Я запускаю приложение С#, и во время выполнения я получаю следующую ошибку:

CLR не смог перейти из контекста COM 0x20e480 в контекст COM 0x20e5f0 в течение 60 секунд. Поток, который владеет целевым контекстом/квартирой, скорее всего, либо выполняет ненакачивание, либо обрабатывает очень длительную операцию без перекачки сообщений Windows. Эта ситуация, как правило, имеет отрицательное влияние на производительность и может даже привести к тому, что приложение становится неактивным или память автоматически накапливается с течением времени. Чтобы избежать этой проблемы, все потоки с одной резьбой (STA) должны использовать примитивы ожидания накачки (например, CoWaitForMultipleHandles) и регулярно накачать сообщения во время длительных операций.

Может кто-нибудь, пожалуйста, помогите мне с проблемой здесь?

Большое спасибо.

Ответ 1

Основной поток вашей программы занят выполнением кода в течение минуты. Он не заботится о своих обычных обязанностях, накачивая цикл сообщений. Это незаконно, когда вы используете COM-серверы в рабочем потоке: призывы к их методам не могут быть отправлены до тех пор, пока ваш основной поток не будет снова простаивать.

Это должно быть легко видно, ваш пользовательский интерфейс должен быть мертв как гвоздь двери. Windows должна была заменить ваше главное окно призраком, который отображает "Не реагировать". Закрытие окна не будет работать, события кликов не будут иметь никакого эффекта.

Независимо от того, что делает ваш основной поток, должен выполняться рабочий поток. Класс BackgroundWorker хорош для этого, вы найдете много информации об использовании в статье библиотеки MSDN. Используйте Debug + Break All, Debug + Windows + Threads, если вы не знаете, что делает основной поток.

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

Ответ 2

Чтобы найти, какая операция блокирует контекстный переключатель и вызывает отображение contextSwitchDeadlock MDA, вы можете использовать следующие шаги. Обратите внимание, что я буду ссылаться на Visual Studio 2012.

  • Воспроизводите ошибку. Это может быть связано с проб и ошибок.
  • Нажмите "ОК", а не "Продолжить" в появившемся окне "Управляемый отладочный помощник".
  • Убедитесь, что панель инструментов Debug Location активна, щелкнув правой кнопкой мыши область стыковки панели инструментов и выбрав "Debug Location". Вы можете увидеть раскрывающийся список с надписью "Thread" на панели инструментов, если он активен.
  • Выбранный элемент в раскрывающемся списке "Нить" должен быть потоком, отличным от основного потока, так как он будет фоновым потоком, который жалуется, что основной поток вызывает все внимание. Выберите основной поток в раскрывающемся списке.
  • Теперь вы должны увидеть код, который блокирует контекстный переключатель в редакторе кода.

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

В отладчике Visual Studio

  • Вы можете отключить MDA непосредственно в диалоговом окне MDA, которое отображается, когда ошибка возникает, сняв флажок "Перерыв, когда это тип исключения ".
  • В диалоговом окне "Параметры исключения", используя приведенные ниже инструкции MSDN.

... в меню "Отладка" выберите "Исключения" . (Если в меню "Отладка" не содержится команды "Исключения" , нажмите "Настроить" в меню "Сервис", чтобы добавить его.) В диалоговом окне "Исключения" разверните список "Управляемые отладки" и снимите флажок "Бросить" для отдельного MDA.

Вне отладчика Visual Studio

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

В моем случае проблема заключалась в вызове ObjectContext.SaveChanges() в Entity Framework в консольном приложении. С MTAThreadAttribute, примененным к методу Main() исключение ContextSwitchDeadlock больше не было создано. К сожалению, я не уверен в полном воздействии этого изменения.

Ответ 3

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

Чтобы на самом деле выяснить, что происходит, вам нужно вломиться в отладчик и посмотреть на все потоки и то, что они делают.

Ответ 4

В некоторых случаях:
Отладка → Исключения → Управляемые помощники по отладке
и снятие отметки с элемента ContextSwitchDeadlock.

Ответ 5

Просто выберите "Исключения из меню" Отладка "в окне" Visual Studio 2005 "," Диалоговое окно "Редактирование", выберите "Исключение исключений управляемых отладок" Node, затем выберите ContextSwitchDeadlock и удалите выбранный из столбца "Бросок". это остановит vs от выброса исключения ContextSwitchDeadlock.

Надеюсь, что это поможет.

Ответ 6

Я столкнулся с этой проблемой, когда пытался выяснить, почему мой OracleDataReader выбрасывает исключение. Я думал, что это было потому, что он получил назначенный null, потому что исключение было связано с параметром, который был "null". Итак, я сделал:

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

Выключил dr был НИКОГДА недействительным, и поэтому цикл продолжался и продолжался до тех пор, пока это сообщение не появилось и еще больше, потому что вы можете нажать "Продолжить", чтобы продолжить, пока не закончится память ( не делайте этого - вместо этого нажмите "ОК" ). Итак, мораль этой истории, ищите утечки памяти, которые передают данные из базы данных в память в циклах до бесконечности. Ошибка на самом деле пытается предупредить вас о плохом сценарии. Лучше всего это прислушаться.

Ответ 7

Эта ошибка возникла для меня много раз, и я проследил ее до итерации в DataGridViewRow, в которой я установил значение флажка в значение true. Поскольку я работал в режиме отладки, у меня была возможность продолжить, поэтому я смог сделать именно это.

Я надеюсь, что это поможет кому-то.