Russian Qt Forum
Ноябрь 22, 2024, 21:36 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3] 4 5 ... 7   Вниз
  Печать  
Автор Тема: Работа из QSerialPort из разных потоков  (Прочитано 46786 раз)
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #30 : Март 24, 2017, 08:44 »

Повторяю в последний раз - БЕЗ ПОТОКОВ! ВООБЩЕ!
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #31 : Март 24, 2017, 08:44 »

http://www.prog.org.ru/topic_30899_0.html
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #32 : Март 24, 2017, 08:57 »

да, я так подозреваю что это QSeraiPort реализован кривовато. От него требуется всего-лишь write и read независимый от потока и все. Все _мои_ проблемы уйдут.

если нужно низкоуровневое управление компортом, то man termios - там и ждать через select/poll можно и читать откуда угодно
Записан
Alechin
Гость
« Ответ #33 : Март 24, 2017, 08:59 »

Повторяю в последний раз - БЕЗ ПОТОКОВ! ВООБЩЕ!
может я закостенел, НО: если программа не должна продолжать выполнение пока я не произведу некоторые действия:
пример: пользователь нажал кнопку "печать". При этом я должен:
1. проверить связь с принтером послав команду условно чтения "статуса 1".
2. при неполучении ответа за отведенное время (очень короткое, 10 мсек максимум) - извещаем пользователя что это невозможно, дальше возвращаемся к основной работе.
3. при получении ответа: анализируем его, в зависимости от установленных флагов либо выполняем новые запросы, либо выдаем управляющие команды и затем отправляем новые запросы.
4. в результате вышеуказанных действий можем либо снова известить пользователя что печать невозможна, либо начинаем набивать в очередь задания для печати и затем запускаем фоновую печать.

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

Вся логика перемещается в слот завершения передачи (для команд, на которые не присылает ответов) и в слот приема ответа. При этом опять же Я ВИЖУ приличный автомат состояний, потому как реакция на получение ответа на запрос, отправленный в разных ситуациях разная.
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #34 : Март 24, 2017, 09:06 »

Код
C++ (Qt)
void MainWindow::onPrintButtonClick()
{
   setEnabled(false);
   QEventLoop loop;
   connect (communicator, &DeviceCommunicator::commandSent, [&loop] (int index, const QByteArray &answer) {loop.quit();});
   communicator.sendCommand(....);
   loop.exec();
   setEnabled(true);
}
 

Вот тебе код, который даст необходимое тебе поведение. Но это хреновый подход. Печать должна идти в фоне, а пользователь должен иметь доступ к остальной функциональности программы.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Alechin
Гость
« Ответ #35 : Март 24, 2017, 09:15 »

конечно печать будет идти в фоне. Но прежде чем начать формирование кучи графики для печати и постановки их в очередь заданий печати хорошо бы убедиться что принтер подключен и отвечает, что он в on-line, что в нем есть бумага, что автобрезчик бумаги закрыт и прочее. При этом почти все ситуации можно исправить отправкой соотв.команд. Примерный цикл 2 байта запрос-один байт ответ занимает ~500 мксек. Соответственно весь процесс ТАКОЙ инициализации печати около 3-5 мсек. В чем такой подход хреновый? Максимальное время блокировки потока (GUI! а не работа с железом! работа с кучей разного железа крутится в паре десятков своих потоков) - это тайм-аут неответа 10 мсек.
(ну просто привычка - основной поток это GUI. он не должен и не делает ничего кроме отображения (ну и управления) кучей (десятки) потоков связанных с разным железом. Потоки железа сами по себе им для работы основной поток и GUI нафиг не нужен. Если им есть что сказать ГУЮ они посылали свои WM_USER.)
а тут получается все в одном ГУЕвом потоке должно крутиться......
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #36 : Март 24, 2017, 09:23 »

Готовность принтера можно проверить в фоне при запуске программы и перепроверять периодически по таймеру.

У меня сейчас сервис на Qt работает по сокетам с автомобильными трекерами, одновременно бывает подключено около 10К трекеров. Вся работа проводится в констексте одного потока и никакой просадки по производительности нет. Не надо пихать потоки туда, где они совершенно не нужны. Забудь про свой борланд и синхронную работу с IO, тут другая кухня.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #37 : Март 24, 2017, 09:26 »

При этом такая последовательность действий может исходить как от пользователя (кнопка на экране), так и от другого потока
Хотя никогда не работал с QSerialPort, но думаю добиться этого несложно. Заводите поток в котором сидит тот же DeviceCommunicator и общаетесь с ним сигналами (QueuedConnection)). Для записи делаете sendCommand слотом (вызываете сигналом, не напрямую). Для получения - ну наверное придется хранить id нитки и посылать его в ответе (чтобы получающий смог различить "ответ для меня").

Но совершенно неясно выдержит ли Ваша архитектура это испытание - ведь тогда разные нитки смогут писать чего хотят, запросы в очереди будут перемешаны произвольным образом, и как с этим разобраться - хз

Код
C++ (Qt)
QQueue<std::tuple<int, QByteArray, int>> commandsQueue_;
 
Видимо, последний писк моды... Улыбающийся Типа "структуры устарели". Все-таки интересно, чего добились? Вместо имен теперь "по номерам" - разве это удобно?
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #38 : Март 24, 2017, 09:30 »

Igors, это псевдокод, мне лень было писать структуру. Если хочешь поговорить об этом, создавай отдельную ветку.

Alechin, представь, что ты строитель. Ты 15 лет скреплял дерево гвоздями и тут тебе дают шурупы и шуруповерт, и говорят - так удобнее. Ты берешь шуруповерт и начинаешь им забивать шурупы в дерево, недоумевая какого хрена они так плохо входят, ведь раньше все с гвоздями отлично работало.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Alechin
Гость
« Ответ #39 : Март 24, 2017, 09:30 »

Готовность принтера можно проверить в фоне при запуске программы и перепроверять периодически по таймеру.

У меня сейчас сервис на Qt работает по сокетам с автомобильными трекерами, одновременно бывает подключено около 10К трекеров. Вся работа проводится в констексте одного потока и никакой просадки по производительности нет. Не надо пихать потоки туда, где они совершенно не нужны. Забудь про свой борланд и синхронную работу с IO, тут другая кухня.
Сокеты и оборудование это несколько разные вещи. Питанием принтера я управляю из программы. Когда что-то надо - я его включаю, надо убедиться что он на связи, потом дождаться его готовности, он может отвалиться в процессе, потом я его отключаю чтобы он аккумулятор не жрал.......
А вопрос в продолжение - а как вы контролируете пропадание самого LAN? ну типа кабель выдернули и снова воткнули? я помню под виндой у меня с этим была проблема.
И если есть USB-RS232 преобразователь его тоже могут вытащить и снова вставить. При этом программа должна автоматически перезапустить работу с ним (пользователя там нет - это автономное оборудование).
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #40 : Март 24, 2017, 09:34 »

У QTcpSocket есть сигнал о закрытии соединения, на него подписываюсь и делаю реконнект. Посмотри сигналы у QSerialPort, там есть сигналы об ошибках.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Alechin
Гость
« Ответ #41 : Март 24, 2017, 09:37 »

 с ним сигналами (QueuedConnection)).
передача в порт 2-ух байтов "напрямую" с ожиданием их выдачи и получением ответа занимает 300 мксек. У меня только прохождение Ququed сигнала начала передачи заняло 20 мсек! т.е. в 66 раз больше!
Для записи делаете sendCommand слотом (вызываете сигналом, не напрямую). Для получения - ну наверное придется хранить id нитки и посылать его в ответе (чтобы получающий смог различить "ответ для меня").
да, получается такое вот упрощение и повышения наглядности ПО.
Но совершенно неясно выдержит ли Ваша архитектура это испытание - ведь тогда разные нитки смогут писать чего хотят, запросы в очереди будут перемешаны произвольным образом, и как с этим разобраться - хз
почему вы все считаете что кто-то одновременно полезет? есть класс работы с принтеров. класс одни. все обращения к принтеру только через него. он сам разруливает кого пустить к принтеру а кого нет.
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #42 : Март 24, 2017, 09:40 »

> У меня только прохождение Ququed сигнала начала передачи заняло 20 мсек!

Что за прохождение? Чем замерял? Вызов слота при выдаче сигнала в однопоточном окружении не несет практически никаких накладных расходов (если используется Qt::AutoConnection)
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #43 : Март 24, 2017, 09:41 »

У меня сейчас сервис на Qt работает по сокетам с автомобильными трекерами, одновременно бывает подключено около 10К трекеров. Вся работа проводится в констексте одного потока и никакой просадки по производительности нет.
Этот сервис использует DeviceCommunicator?
Идея этого класса хорошая, спасибо за науку  Улыбающийся
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
Alechin
Гость
« Ответ #44 : Март 24, 2017, 09:42 »

У QTcpSocket есть сигнал о закрытии соединения, на него подписываюсь и делаю реконнект. Посмотри сигналы у QSerialPort, там есть сигналы об ошибках.
в Винде "закрытие соединения" (тем более которого нет в UDP) и "пропадание LAN" не одно и тоже. Для UDP с выдернутым кабелем сокет продолжал "успешно" пихать данные и говорить что все Ok. Пришлось заводить отдельный поток (не ругайтесь!) который раз в секунду пытался создать новое соединение и при создании при обрыве кабеля уже возвращалась ошибка.
Для USB-COM еще хуже. если выдернуть преобразователь - ошибка не возвращается. Более того - хендл порта продолжает существовать и по нему успешно "пишутся" данные. И если при восстановлении LAN хотябы хендлы сохраняются и работа просто возобновляется дальше, то для USB-COM при втыкании USB порту назначался тоже номер, но новый хэндл!
Записан
Страниц: 1 2 [3] 4 5 ... 7   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.167 секунд. Запросов: 23.