Chr*_* K. 14 c++ boost timeout serial-port boost-asio
我需要知道如何读取(同步或异步并不重要)超时.我想检查设备是否与串口连接.
为此我使用asio::write
然后我等待设备的响应.
如果设备连接asio::read(serial, boost::asio::buffer(&r,1))
正常,但如果没有设备程序停止,这就是我需要超时的原因
我知道我需要一个,deadline_timer
但我不知道如何在async_read
函数中使用它.
它的工作原理的一个例子将非常有用.
我知道有许多类似的线程,我读了很多,但我找不到一个解决方案,帮助我解决我的问题!
Rob*_*ner 11
Igor R.发布的代码没有为我编译.这是我的代码的改进版本,它完美地运行.它使用lambdas来摆脱set_result
辅助函数.
template <typename SyncReadStream, typename MutableBufferSequence>
void readWithTimeout(SyncReadStream& s, const MutableBufferSequence& buffers, const boost::asio::deadline_timer::duration_type& expiry_time)
{
boost::optional<boost::system::error_code> timer_result;
boost::asio::deadline_timer timer(s.get_io_service());
timer.expires_from_now(expiry_time);
timer.async_wait([&timer_result] (const boost::system::error_code& error) { timer_result.reset(error); });
boost::optional<boost::system::error_code> read_result;
boost::asio::async_read(s, buffers, [&read_result] (const boost::system::error_code& error, size_t) { read_result.reset(error); });
s.get_io_service().reset();
while (s.get_io_service().run_one())
{
if (read_result)
timer.cancel();
else if (timer_result)
s.cancel();
}
if (*read_result)
throw boost::system::system_error(*read_result);
}
Run Code Online (Sandbox Code Playgroud)
不要使用deadline_timer
在async_read
.但是你可以启动两个异步进程:
async_read
串口过程.boost :: asio :: serial_port有一个取消方法,可以取消对它的所有异步操作.deadline_timer
您可以cancel
使用串行端口.这应该关闭async_read
操作并调用其完成处理程序并显示错误.码:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/array.hpp>
class timed_connection
{
public:
timed_connection( int timeout ) :
timer_( io_service_, boost::posix_time::seconds( timeout ) ),
serial_port_( io_service_ )
{
}
void start()
{
timer_.async_wait
(
boost::bind
(
&timed_connection::stop, this
)
);
// Connect socket
// Write to socket
// async read from serial port
boost::asio::async_read
(
serial_port_, boost::asio::buffer( buffer_ ),
boost::bind
(
&timed_connection::handle_read, this,
boost::asio::placeholders::error
)
);
io_service_.run();
}
private:
void stop()
{
serial_port_.cancel();
}
void handle_read ( const boost::system::error_code& ec)
{
if( ec )
{
// handle error
}
else
{
// do something
}
}
private:
boost::asio::io_service io_service_;
boost::asio::deadline_timer timer_;
boost::asio::serial_port serial_port_;
boost::array< char, 8192 > buffer_;
};
int main()
{
timed_connection conn( 5 );
conn.start();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
曾几何时,库作者提出了以下与超时同步读取的方法(此示例涉及tcp::socket
,但您可以使用串口代替):
void set_result(optional<error_code>* a, error_code b)
{
a->reset(b);
}
template <typename MutableBufferSequence>
void read_with_timeout(tcp::socket& sock,
const MutableBufferSequence& buffers)
{
optional<error_code> timer_result;
deadline_timer timer(sock.io_service());
timer.expires_from_now(seconds(1));
timer.async_wait(boost::bind(set_result, &timer_result, _1));
optional<error_code> read_result;
async_read(sock, buffers,
boost::bind(set_result, &read_result, _1));
sock.io_service().reset();
while (sock.io_service().run_one())
{
if (read_result)
timer.cancel();
else if (timer_result)
sock.cancel();
}
if (*read_result)
throw system_error(*read_result);
}
Run Code Online (Sandbox Code Playgroud)
本身没有一个或简单的答案,因为即使您执行异步读取,回调也永远不会被调用,并且您现在在某处有一个松散的线程。
您假设这deadline_timer
是可能的解决方案之一是正确的,但它需要一些调整和共享状态。有一个阻塞 TCP 示例,但仅此而已,async_connect
当它无事可做时返回它是一件很酷的事情。read
不会这样做,最坏的情况是——它会因为无效的资源而崩溃并烧毁。所以这deadline timer
件事是你的选择之一,但实际上有一个更简单的选择,有点像这样:
boost::thread *newthread = new boost::thread(boost::bind(&::try_read));
if (!newthread->timed_join(boost::posix_time::seconds(5))) {
newthread->interrupt();
}
Run Code Online (Sandbox Code Playgroud)
基本上,在另一个线程中进行读取,如果超时则将其终止。您应该阅读Boost.Threads。
如果中断它,请确保资源全部关闭。
归档时间: |
|
查看次数: |
19765 次 |
最近记录: |