Исключение между потоками - только среда - PullRequest
5 голосов
/ 01 июня 2011

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

  1. У меня есть DataGridView с источником данных на основе BindingList <>.
  2. У меня есть рабочий поток (не-GUI), который выполняет некоторые модные вычисления / сравнения / и т.д., а затемдобавляет / редактирует объект в / в BindingList <>.
  3. В таймере поток GUI обновляется против BindingList <>.

Этот код работает безупречно - до тех пор, покатак как я не бегаю в окружающей среде.В среде, когда метод .Add () вызывается в BindingList <>, я получаю небольшую полезную ошибку:

An Exception has occurred
EXCEPTION : Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.
IN METHOD : get_Handle
AT LINE   : 0
CLASS     : System.Windows.Forms.Control

Обратите внимание, что имя нарушаемого элемента управления пусто ... Я думаю, что если бы проблема была в обновлении BindingList <>, не было бы никакого значения, работаю ли я в среде или нет.Несмотря на это, это то, что я вижу. Более того, .Add () завершается успешно, хотя генерируется исключение !!

Очевидно, что в моей производственной среде это не имеет большого значения (пока?), Поскольку это происходит только в Studio;и да, я мог бы вызвать поток GUI для выполнения добавления или сохранить добавления в месте, где поток GUI мог бы извлечь их позже ... Я не ищу обходной путь, но тем болеезаинтересован в ответе на этот вопрос:

Почему ошибка появляется только в студии?

Ответы [ 3 ]

4 голосов
/ 01 июня 2011

Ошибка может возникнуть только в VS, если это MDA ( Managed Debugging Assistant ), а не исключение времени выполнения. MDA всегда готовы сообщить вам, когда вы делаете что-то, что обычно, но не всегда на 100%, то, что может привести к неприятностям в производственном коде (что, в конечном счете, и будет, даже если это будет работать в 99% случаев на твоя машина).

Вы должны вызывать поток пользовательского интерфейса для выполнения метода Add.

РЕДАКТИРОВАТЬ: Чтобы быть на 100% тщательным ... Без Reflector (так как мой истек - вы слушаете Red Gate ?!) Я предполагаю, что класс Control проверяет, находитесь ли вы в потоке пользовательского интерфейса, выдает исключение на фоновый поток, если это не так, а затем перерисовывает пользовательский интерфейс в любом случае. Поскольку фоновый поток уже добавил элемент, перерисовка пользовательского интерфейса видит его и перетягивает его в пользовательский интерфейс, как и ожидалось, но ваш фоновый поток все еще видит исключение, и вы либо молча глотаете его в блоке перехвата, либо фоновый поток завершается (что в вашем приложении может быть допустимым, например, BG-поток является потоком потоков).

3 голосов
/ 01 июня 2011

Ошибка появляется только в VS, потому что это своего рода диагностическое сообщение, пытающееся сообщить вам, что у вас есть ошибка.И в производстве эти дополнительные проверки по умолчанию отключены.Так что ошибка всегда есть, но вы получаете уведомление только во время отладки.

Я не слишком знаком с многопоточным программированием WinForms, но я предполагаю, что, поскольку вы вызываете add to the list списка в другом потоке, изменениеуведомления происходят и в этом другом потоке, и, поскольку вы связываете элемент управления, он будет изменять его состояние во время такого уведомления.Это означает, что доступ к элементу управления осуществляется из неправильного потока, что является ошибкой.

1 голос
/ 01 июня 2011

Я думаю, что это происходит постоянно;однако ошибки привязки обычно игнорируются (например, BindingSource.DataError ).Visual Studio перехватывает обработанные исключения - чтобы выделить ошибку.

Наличие элемента управления с привязкой к данным (DataGridView) и коллекции с привязкой требует проблем, если вы затем обновите их из другого потока.Природа "наблюдателя" заставляет его делать обновления в потоке пользовательского интерфейса.В прошлом я пытался обойти это, но я думаю, что вам следует полностью отключить привязку данных и обновить вручную.И не забывайте, что ручное обновление и фоновые изменения должны оба синхронизировать доступ, чтобы они не боролись.

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

...