Вызовите событие в одном потоке для вызова методов во втором потоке - PullRequest
4 голосов
/ 17 мая 2011

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

  • Один для основной программы
  • Второй, который прослушивает сокет, анализирует ввод и вызывает соответствующее событие.

Дополнительные требования:

  1. Приложение не должно полагаться на поток пользовательского интерфейса (его можно запустить как консольное приложение).
  2. Основная программа должна обрабатывать сообщения синхронно, то есть в том порядке, в котором они поступили.
  3. Главный поток не должен блокироваться при ожидании таймеров (я полагаю, это означает, что я должен запускать таймеры наразные темы).

А теперь несколько вопросов: -):

  1. Я предполагаю, что требование № 1 означает, что у меня нет встроенного сообщениянасос, поэтому я не могу использовать Invoke() из потоков слушателя / таймера сокета.Это правильно?
  2. Как можно безопасно вызывать события в одном потоке (например, в прослушивателе) и синхронно запускать подписчики в другом потоке (основном потоке)?
  3. Весьма вероятно, чтоновые события будут вызваны до того, как будет сделан следующий обработчик.Что будет в этом случае?Будет ли событие буферизовано где-то CLR или оно будет проигнорировано?

И последнее, но не менее важное: я предполагаю, что стремлюсь к параллели для парадигмы «производитель / потребитель», но вместо этогосообщений, я хочу использовать события.Как вы думаете, есть лучший подход?

Спасибо,

Боаз

РЕДАКТИРОВАТЬ

Я хочу объяснить мою мотивацию дляиспользуя события в первую очередь.Приложение представляет собой автоматизированный торговый механизм, который должен реагировать на события, происходящие на рынке (например, изменение цены акции).Когда это происходит, в главном потоке может быть несколько подписчиков, которые следует вызывать, что является классическим сценарием использования событий.

Полагаю, я всегда могу использовать Producer / Consumer с какой-либо очередью сообщений и получать от потребителей события в главном потоке, но я подумал, что может быть более прямой путь.

Ответы [ 2 ]

4 голосов
/ 17 мая 2011

Я думаю, что использование сообщений будет самым простым способом. Если вы используете C # 4, это очень легко благодаря BlockingCollection <>

Итак, используйте общий BlockingCollection, где Message - это класс вашего сообщения.

Затем в вашем рабочем потоке вы делаете это

var msgEnum = blockingCollection.GetConsumingEnumerable();

//Per thread
foreach( Message message in msgEnum )
{
   //Process messages here
}

Вот и все.

GetConsumingEnumerable () будет блокироваться до тех пор, пока не появится сообщение для обработки. Затем он удалит сообщение из очереди, и ваш цикл обработает его.

Что приятно в этом, так это то, что вы можете добавлять больше потоков, и в каждом из них у вас просто есть цикл foreach.

Когда вы закончите, вызовите blockingCollection.CompletedAdding ();

Кстати, очередь обрабатывает параллелизм и будет помещать в очередь сообщения, отправленные одновременно и т. Д.

Надеюсь, это поможет

Andre

2 голосов
/ 17 мая 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...