Равенство и объявление DateTime приводит к ContextSwitchDeadlock - PullRequest
1 голос
/ 27 января 2012

Я думаю, что это глупый вопрос, но мне было немного странно обнаружить, что я не могу сделать следующее:

EditingItem.FROM = EditingItem.TO = DateTime.Now;   // FROM, TO are DateTime   

после этих манипуляций программа иногда зависает, но иногда это просто работает так, как я думал.
Вот исключение:

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

Изменение кода на:

  EditingItem.FROM = DateTime.Now;
  EditingItem.TO = DateTime.Now;

помогает в моей ситуации.

Не можете правильно задать вопрос Google, чтобы увидеть объяснение, так что вы можете помочь и объяснить, почему выражение неверно?
PS подробнее в комментариях.Вот некоторые результаты экспериментов:

DateTime d = DateTime.Now;
EditingItem.FROM = EditingItem.TO = d;//hang

добавлен цикл для синхронизации:

for (int i = 0; i < 100000; i++)
{
   i++;
}

DateTime d = DateTime.Now;
EditingItem.FROM = EditingItem.TO = d;//hang

Ответы [ 2 ]

2 голосов
/ 27 января 2012

Ваша проблема в том, что, кажется, происходит lock - опять-таки, код не предоставлен, поэтому просто предположите - где объект заблокирован, так что назначение свойства из другого свойства заблокирует само себя.

Если вы имеете дело с COM, это может быть связано с тем, что COM-объекты являются однопотоковыми объектами Apartment.

2 голосов
/ 27 января 2012

Ваш код эквивалентен следующему:

var temp = DateTime.Now;
EditingItem.TO = temp;
EditingItem.FROM = temp;

Поместить назначения в одну строку - это просто сокращение, которое, возможно, показывает корни языка C в C #.

Теперь, когда выпредоставили больше информации о вашей проблеме, кажется, что ваша программа зависает из-за COM-блокировки.Трудно понять, как назначение значений DateTime может привести к этому тупику.Исключение указывает на то, что CLR пытается вызвать COM-объект в STA (однопотоковая квартира), который не обрабатывает свой обработчик сообщений.

Я просто пытаюсь описать возможный сценарий, но знаю оподробности вашей проблемы Я могу быть далеко:

Допустим, у вас есть пользовательский интерфейс на основе COM, который отвечает на событие (например, щелчок).В обработчике событий запускается фоновый поток, а затем обработчик событий ожидает завершения этого потока или установки сигнала о завершении фоновой задачи.Фоновая задача (запущенная в другом потоке) затем пытается получить свойство для COM-объекта.Это вызовет тупик, подобный тому, который вы испытываете.

Фоновый поток, работающий в другой квартире, отличной от элемента управления COM, должен маршалировать вызов в квартиру элемента управления COM (STA).Это делается путем отправки сообщения Windows в скрытое окно, используемое COM.Однако поток, который должен отправить это сообщение Windows, в настоящее время заблокирован, ожидая завершения фонового потока.Фоновый поток ожидает, пока поток пользовательского интерфейса не отправит сообщение Windows.Это тупик.

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

...