EP>Этот код точно не работает? А если создать полностью новый serial_port, после деструкции старого? (можно использовать optional<serial_port>)
У меня получилось повторно открыть порт, только с новым объектом порта и (одновременно) новым объектом io_service для него.
При этом предыдущий объект порта И его объект io_service должны быть уничтожены(вызван деструктор для них).
Здравствуйте, niXman, Вы писали:
EP>>.close() по идее должен завершать все хэндлеры с boost::asio::error::operation_aborted. X>нет. при close(), хендлеры вызовутся с end_of_file, а при cancel() — operation_aborted
Я же ссылку привёл, а по ней:
This function is used to close the serial port. Any asynchronous read or write operations will be cancelled immediately, and will complete with the boost::asio::error::operation_aborted error.
cancel() тоже не помогает.
Насколько я видел код close() просто закрывает хендл порта. Но, опять же насколько я представляю, а представляю я пока слабо, внутри (всей кухни управления COM портом) используется механизм
портов завершения вводы\вывода и если какая-то из функций этого механизма "держит" хендл, то фактически закрытия не происходит при вызове close().
Те перед close() надо сделать еще какие-то правильные действия в правильной последовательности.
Точно не могу сказать, вроде, нет.
Ты можешь вызвать port.close(), а потом у сервиса service.poll() или service.run() и тогда он вызовет хендлер с какой-то ошибкой(типа порт закрыт) соответственно.
Но это не значит, что Windows HANDLE порта правильно закрылся после этого...хотя — ...надо разбираться)))
Здравствуйте, HolyNick, Вы писали:
HN>Точно не могу сказать, вроде, нет. HN>Ты можешь вызвать port.close(), а потом у сервиса service.poll() или service.run() и тогда он вызовет хендлер с какой-то ошибкой(типа порт закрыт) соответственно.
Если .close() не вызывает, хотя документация говорит что должен — то по всей видимости там баг, и нужно открывать ticket.
Какая версия boost? И можешь привести минимальный пример однозначно воспроизводящий проблему (можно добавить вывод в cout внутри хэндлера, до и после вызова close/cancel).
Бага там нет, если ты запустил где-то service.run(), а потом вызвал port.close(), то он все обработчики вызовет.
Я-то service.run() вообще никогда не вызываю(не использую), только service.poll(), поэтому и после закрытия(port.close()) порта мне нужно вызвать service.poll(), как я указал в предыдущем примере.
PM>Телепатически предполагаю что все дело в выделенном — для нормальной работы асинхронного I/O у io_service нужно вызывать run(), run_once() или poll().
Да. И еще похоже, что нужно делать вызов reset(), о чем в общем-то написано в исходниках :
boost::asio::io_service service;
std::shared_ptr<boost::asio::serial_port> port(new boost::asio::serial_port(service));
port->open("COM3"); //OK
char buffer;
boost::asio::async_read(*port, boost::asio::buffer(&buffer, 1),
[port](boost::system::error_code error, std::size_t bytes_transferred)
{
int i = 0;
i++;
});
port->close();
service.poll();Вызовется обработчик из предыдущего async_read
service.reset();если не вызвать, то следующая команда poll не вызовет обработчик
port->open("COM3");//OK
char buffer2;
boost::asio::async_read(*port, boost::asio::buffer(&buffer2, 1),
[port](boost::system::error_code error, std::size_t bytes_transferred)
{
int i = 0;
i++;
});
port->close();
service.poll();Вызывает обработчик, только если был вызов reset()
port->open("COM3");//OK, только если был вызов reset(), в противно случае ACCESS DENIED и исключение
Если я использую в программе два COM(boost::asio::serial_port) порта каждый из которых использует свой отдельный объект io_service, могу ли я работать(делать вызовы poll()) с портами(и соответстсвенно сервисами) в разных потоках? Какие там подводные камни? Или надо для каждого порта запускать свой поток и опрашивать порт только в нем?
Спасибо.
X>а зачем тебе два io_service`а? или ты все еще продолжаешь писать "лишь бы работало"?
Пока разбираюсь. Но вопрос актуален даже если один и тот же сервис на оба порта.
X>а зачем тебе дополнительные потоки(threads)? чем асинхронный IO не угодил?
Основной поток реагирует на нажатия кнопочек окошка, второй пишет\читает(выполняет задачу) из порта.
Здравствуйте, HolyNick, Вы писали:
HN>Основной поток реагирует на нажатия кнопочек окошка, второй пишет\читает(выполняет задачу) из порта.
так интегрируй io_service::poll_one() в event loop твоей апликухи. и не нужно никаких дополнительных потоков.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, niXman, Вы писали:
X>Здравствуйте, HolyNick, Вы писали:
HN>>Основной поток реагирует на нажатия кнопочек окошка, второй пишет\читает(выполняет задачу) из порта. X>так интегрируй io_service::poll_one() в event loop твоей апликухи. и не нужно никаких дополнительных потоков.
Да, согласен. (спасибо за подсказку)
ps: просто с парой потоков, при некотором условии, переставали вызываться обработчики(handler'ы) порта — хотелось понять почему (на будущее)