Как в C# передать сообщение из дочернего потока в главный?
Мне нужно получать информацию с двух плат. Сами платы реализованы через пень колоду и в них нет режима прерывания, потому в двух потоках у меня будет в бесконечном цикле получаться с них информация и сравниваться с предыдущим значением. Если значение меняется, то это новое значение главный поток у меня должен будет обработать, а второстепенный поток должен продолжить получать информацию с платы. Если я сделаю событие и буду его генерировать при изменении, то его обработчик будет работать в том-же потоке, что мне не подходит. В голову приходят только программные прерывания на уровне ядра, но я не имею ни малейшего понятия, как это делается.
Это C#, говорить о производительности в таких вопросах уже не приходится. Чтоб получить доступ к железу так или иначе, но у вас уже есть переключение контекста, это дорогая операция, по сравнению со всем остальным.
Ну раньше было написано на VB.NET .NET 2.0. Работало более менее. Качество кода отвратительное и сделано через критические секции синхронизация. Если у меня щас получится сделать по шустрее, то будет хорошо.
Получилось очень даже быстро. Время импульса 20 миллисекунд. Я обращаюсь к плате каждые 0.002 миллисекунды. Можно теперь даже устройство чуть изменить. Причем мне кажется, что можно еще ускорить, если использовать не .NET, а С++. А уж если и сам драйвер переписать, то можно будет делать прерывания, благо на плате они поддерживаются, судя по схеме.
queue прикрутить. один поток выгребает из очереди все и делает дело, остальные потоки дергают платы и если надо - добавляют сообщение в очередь.
на примитивах типа Monitor.Wait / Monitor.Pulse очередь очень простая получается.
заодно решается проблема, когда значения изменяются быстрее, чем обрабатывается факт изменений.
Синхронизация данных не нужна мне. У меня данные не будут приходить чаще 600 раз в минуту. А уж по полученному байту сгенерировать еще пару байт текущим компам не проблема.Добавление синхронизации только ухудшит время реакции. Мне по хорошему вообще нужно реальное время, но для этого ОС потребуется менять. Щас копаюсь с диспетчером, так вроде быстрее будет.
Устройство, что подключено к плате сбора данных будет максимум менять инфу раз 600 в минуту. Но вот плата, которая эти данные считывает и уже выдает в цифровом формате не имеет режима прерывания. Я могу только обращаться к ней с командой чтения текущего значения. Что бы зафиксировать момент, когда придет импульс на эту плату мне нужно в бесконечном цикле к ней обращаться и сверять данные. Если такой цикл повесить в главном потоке, то он повесит всю систему. А у меня таких платы две штуки. Учитывая, что компы щас по 2 ядра с гиперпоточностью минимум, а то и 4 полноценных ядра имеют, то мне лучше каждую плату вытащить в отдельный поток. И да я знаю, что все это очень убого выглядит, но выбросить эти платы я не могу в текущем проекте, благо в будущем их уже не будет.
Для абстракции. Два класса просто выдают инфу о том, что данные на входе изменились. Другой класс представляет подключаемое устройство и там будет идти обработка этих значений для генерации более выскоуровневых событий. Дальше прога уже будет использовать класс подключаемого устройства.
То как ты мне рекомендуешь, то мне везде потребуется работать уровне самой платы и если к примеру интерфейсы для ее доступа или формат выдаваемого значения кардинально изменится, то мне потребуется менять всю прогу. Чем я сейчас и занимаюсь. Драйвера для платы кардинально изменились, по другому ее настраиваем и данные выдает в совершенно по другому. Старые драйвера использовать нельзя, тк они WinXP only, а ее уже не продают.
Чуть позже устройство приема будет уже заменено и менять всю прогу мне нет желания. А еще в планах возможность подключения нескольких устройств. Спасибо не хочу делать одну и ту-же работу по несколько раз. Предусмотри разработчики такое развитие событий ранее, у меня было бы гораздо меньше работы сейчас.