Почему исключение операции перекрестного потока не выбрасывается при запуске exe в bin\Debug

Я отлаживал приложение и где-то в коде, поток пытается получить список, созданный другим потоком. При попытке получить доступ к списку, приложение выдает "Неверная операция перекрестного потока: контрольный список", доступ к которому был получен из потока, отличного от потока, который был создан при исключении во время отладки. Тем не менее, когда я запускаю вывод этого приложения в папке bin\Debug, я не получаю диалоговое окно с исключениями, и я вижу, что список успешно доступен из потока, не являющегося владельцем, поэтому это заставляет меня думать, что существует поведенческая разница здесь, а не только исключенное исключение. Я могу пройти это исключение в отладке со следующей строкой в ​​событии form_load

Control.CheckForIllegalCrossThreadCalls = false;

Но в чем причина этого различного поведения?

Ответ 1

Да, это проверяется только при подключении отладчика. Это было необходимо, потому что было много кода .NET 1.x, который нарушил это правило. Это не очевидно.

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

Microsoft много заботится о отсталой совместимости, даже если это багги. Исправление отличное, хотя иногда это неправильно (Show (owner) проверяется, когда он не должен). И иногда пропускает проверку, когда это код в структуре, которая нарушает правило. Это происходит, когда зависимость потока является косвенной. Наиболее распространенными случаями этого являются обновление источника данных связанного с данными управления в рабочем потоке (сначала отключайте!) И используя элемент управления, который прослушивает событие SystemEvents.UserPreferenceChanged(не создавайте интерфейс во втором потоке!)


Для справки соответствующий код присутствует в статическом конструкторе класса Control:

static Control()
{
    //...
    checkForIllegalCrossThreadCalls = Debugger.IsAttached;
    //...
}