asio ::暂停阅读



我需要知道如何读取(同步或异步无关紧要)与超时。我想检查设备是否与串行端口连接。

为此我使用asio::write,然后等待设备的响应。

如果连接设备asio::read(serial, boost::asio::buffer(&r,1))工作正常,但是如果没有设备,则程序停止,这就是为什么我需要超时

我知道我需要deadline_timer,但我不知道如何在async_read函数中使用它。

它如何工作的一个例子真的很有帮助。

我知道有很多类似的线程,而且我读了很多线程,但是我找不到可以帮助我解决问题的解决方案!

igorR发布的代码没有为我编译。这是我改进的他的代码版本,可以很好地工作。它使用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);
}

从来一次,库作者提出了以下方法,以同步读取与超时的读数(此示例涉及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); 
  } 

您在async_read中不使用deadline_timer。但是您可以启动两个异步过程:

  1. 串行端口上的async_read进程。boost :: asio :: serial_port具有一种取消方法,可以取消所有异步操作。
  2. 截止时间器具有所需的超时。在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;
}

没有一个人或 Easy 答案本身,因为即使您进行异步阅读,回调也永远不会被调用,现在您在周围的某个地方有一个松散的线程。

您假设deadline_timer是可能的解决方案之一,但是它需要一些摆弄和共享状态。有一个阻碍的TCP示例,但这是针对async_connect的,当它无事可做时,它返回的事情很酷。read不会这样做,最坏的情况 - 它将崩溃&amp;烧毁无效资源的原因。因此,deadline timer是您的选择之一,但是实际上有一个更容易的事物,有点像这样:

boost::thread *newthread = new boost::thread(boost::bind(&::try_read));
if (!newthread->timed_join(boost::posix_time::seconds(5))) {
    newthread->interrupt();
}

基本上,在另一个线程中进行读取并将其杀死。您应该在boost.threads上阅读。

如果中断它,请确保资源全部关闭。

相关内容

  • 没有找到相关文章

最新更新