Обработка событий в поточной архитектуре - PullRequest
0 голосов
/ 20 сентября 2010

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

Проблема, которую я знал, заключалась в следующем:

Предположим, есть две нити: Нить A и Нить B .

Поток A - это то, что вы увидите в методе Static Void Main как единственный поток.

Поток A создает объект с асинхронными методами Start / Stop и применяет обработку событий к этому объекту.

Когда в объекте вызывается метод Start из Thread A , он создает новый поток для этого объекта для обработки информации из свойств объекта или входных данных, который является Thread B . (В моем случае процессы приема и отправки по сети выполняются по моему собственному протоколу.)

Когда объект в Потоке B завершен при получении новой информации от входа или свойства, Поток B вызывает событие в объекте для передачи данных в Поток A .

Проблема в том, что когда событие вызывалось, оно управлялось Thread B . Поток B должен был выполняться только на этом объекте, чтобы продолжать выполнять метод обработки, но вместо этого он переходил к другому объекту и позже имел конфликт между потоками между Потоком A и Поток B , когда предполагается передать событие Поток A для Поток A для обработки этого нового вывода.

Если Поток A - это тот, который инициализирует объект и класс, на котором он работал, почему, когда событие было вызвано, оно запускается в Потоке B вместо этого?

Мне нужно было Поток B , чтобы продолжить цикл навсегда и не прерывать программу, передавая информацию о событии в Поток A .

Пожалуйста, извините за мой английский и грамматику и спасибо за ваше терпение. : -)

[РЕДАКТИРОВАТЬ x4] Если вы хотите получить исходный код, он находится здесь: http://fcpfoundation.codeplex.com/ (сейчас.)

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

Ответы [ 2 ]

2 голосов
/ 21 сентября 2010

По умолчанию обратный вызов происходит в потоке, который запускает обратный вызов (поток B). Это потому, что нет единого правильного способа для потока B сообщить потоку A, что у него есть что-то для выполнения. В конце концов, когда поток А должен его выполнить? Вы не хотели бы, чтобы поток B фактически прерывал поток A, так как он может быть занят выполнением чего-то важного, и прерывание может привести к тому, что программа окажется в недопустимом состоянии для выполнения кода, предоставляемого потоком B. Представьте, что произошло следующее:

  • Нить A запрашивает нить B, чтобы сообщить ей, когда произошел X.
  • Тема A начинает сортировку списка важной информации.
  • Поток B говорит Потоку A прекратить то, что он делает, потому что произошел X.
  • Поток A начинает отвечать на X, но он был в середине сортировки, поэтому список находится в недопустимом состоянии, что вызывает проблемы при обработке X.

Чтобы поток А мог что-то сделать на основе X, ему нужно попасть в безопасное место, где он не занят чем-то другим. В основном потоке пользовательского интерфейса приложения это происходит в так называемом насосе сообщений, где Windows выдает приложениям такие сообщения, как «пожалуйста, нарисуйте себя» или «мышь только что переместилась». Вы можете использовать насос сообщений для публикации собственных сообщений, используя Control.Invoke , чтобы запланировать выполнение некоторого кода в потоке пользовательского интерфейса.

Если поток А не является потоком пользовательского интерфейса, вам необходимо придумать собственный дизайн для того, как поток А получает сообщение из потока Б и обрабатывает его в свое время.

0 голосов
/ 21 сентября 2010

Может быть, это слишком упрощает проблему, но вы рассматривали какой-то потокобезопасный насос сообщений FIFO? то есть поток B может отправлять уведомления о событиях в очередь FIFO, которую отслеживает поток A. Так как это «запустить и забыть», Нить B может публиковать и продолжать свой путь, не заботясь о том, что делает Нить. Поток A может затем отслеживать сообщения и извлекать их из очереди по мере необходимости.

Публичный статический экземпляр System.Collections.Queue или System.Collections.Generic.Queue оба являются потокобезопасными.

...