Почему возникает ошибка доступа к контролу из другого потока?

Сразу оговорюсь, вручную потоки я не создаю в коде. Но может быть дело в использовании класса, который управляет взаимодействием через SerialPort?
Стараюсь придерживаться шаблона MVP.
Presenter инстанцируется после запуска приложения и получается указатели на созданные экземпляры классов форм и класса SerialPortManager, который управляет соединением через COM-порт.
Если обработчик события, в котором я меняю контролы на формах, висит на событиях с самих форм - всё ОК.
Или, если просто обратиться в Presenter-е к контролам (через сеттеры, описанные в интерфейсах, которые реализуют классы форм) - тоже хорошо.
Но если обработчик в Presenter повесить на кастомное событие, которое генерится в объекте класса SerialPortManager (а оно там возникает после постобработки события SerialPort.DataReceived), тогда всё. Кирдык.

Получается что?
1) Объект, работающий с SerialPort находится в отдельном потоке?
2) Обработчик, которые лезет к контролам, описан в другом классе (в Presenter), почему же в зависимости от источника события разные потоки получаются?

Прошу без фанатизма, совсем недавно начал разбираться с C#.
  • Вопрос задан
  • 375 просмотров
Решения вопроса 1
Nipheris
@Nipheris Куратор тега C#
> Объект, работающий с SerialPort находится в отдельном потоке?

Цитирую из https://msdn.microsoft.com/en-us/library/system.io... :

The DataReceived event is raised on a secondary thread when data is received from the SerialPort object. Because this event is raised on a secondary thread, and not the main thread, attempting to modify some elements in the main thread, such as UI elements, could raise a threading exception. If it is necessary to modify elements in the main Form or Control, post change requests back using Invoke, which will do the work on the proper thread.

А вообще, если есть еще какая-то логика обработки данных, приходящих из порта, то лучше вызывать ее в ивенте DataReceived, и уже в ней, после необходимой обработки, отправлять более высокоуровневые сообщения в GUI-поток через какую-нибудь очередь сообщений, например организованную с помощью ConcurrentQueue. Тогда ваш GUI-поток будет дергаться не по приходу пары байт, а тогда, когда вам самим это будет нужно. Но это уже архитектурный вопрос, который я вас советую продумать, если у вас не одноразовая лаба.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы