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


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

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

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

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

8 74

8 ответов:

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

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

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

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

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

  1. воспроизвести ошибку. Это может быть методом проб и ошибок.
  2. Нажмите кнопку "ОК", а не "продолжить" в управляемом помощнике отладки, который отображается.
  3. убедитесь, что панель инструментов расположение отладки активна справа нажмите на область закрепления панели инструментов и выберите "место отладки". Вы должны увидеть выпадающий список с надписью "поток" на панели инструментов, если он активен.
  4. выбранный элемент в выпадающем списке потока должен быть потоком, отличным от основного потока, поскольку это будет фоновый поток, который жалуется, что основной поток забивает все внимание. Выберите основной поток в раскрывающемся списке.
  5. теперь вы должны увидеть код, который блокирует переключение контекста редактор кода.

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

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

  1. вы можете отключить MDA непосредственно в диалоговом окне MDA, которое отображается при возникновении ошибки, сняв флажок ' Break когда это выбрасывается тип исключения'.
  2. с диалогом настроек исключений, используя инструкции ниже от MSDN.

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

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

  1. Ключ Реестра (машина широкая, все затронутые MDAs)
  2. Переменные Среды (машина широкая, MDAs можно определить)
  3. Настройки Настройки Приложения (область применения, MDAs может быть указан)

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

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

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

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

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

просто выберите исключения из меню отладка в окне visual studio 2005, диалоговое окно Edxception всплывающее окно wil, выберите узел исключение управляемых помощников отладки, затем выберите ContextSwitchDeadlock и удалите столбец select from Thrown . это остановит vs от бросания исключения ContextSwitchDeadlock.

надеюсь, что это помогает..

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

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

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

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

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

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