2016-07-26 6 views
1

私は最近boost :: asioの非同期タスクに関する問題を発見しました。私はポートを聴いているオブジェクトにポインタを戻したい。 これはsocket.read_someメソッドを使用すると機能しますが、このメソッドはメインをブロックし、MyClass :: createメソッドを返すようにします。Boost Asio - なぜ私の非同期操作は起動しないのですか?

私はasync_read呼び出しを試みましたが、私のread()メソッドの中で、非同期タスクは起動していないことがわかりました。私は何が問題を引き起こす可能性があるのか​​把握しようとしましたが、この問題の解決策はありません。

ここに私のコードはありますが、ここではasync_readではなくasync_waitであり、同じ問題が現れ、タイマーは起動しません。

お手数ですがお手数ですが、

ヘッダファイル:

#ifndef MYCLASS_HPP 
#define MYCLASS_HPP 

#include <memory> 
#include <boost/asio.hpp> 

class MyClass 
{ 
public: 
MyClass(boost::asio::io_service& ios); 

void read(); 
void read_handler(const boost::system::error_code& error); 

static std::shared_ptr<MyClass> create(std:: string const & host, uint16_t port); 

bool connect (std::string const & host, uint16_t port); 
void connect_handler(const boost::system::error_code& error); 


boost::asio::ip::tcp::socket m_socket; 
bool    m_flag; 
std::vector<uint8_t>  m_buffer; 
}; 

#endif 

ソースファイル:

#include "MyClass.hpp" 

#include <boost/bind.hpp> 

MyClass::MyClass(boost::asio::io_service& ios) 
    :m_flag(false), m_socket(ios), m_buffer(20) 
{ 
} 

void MyClass::read_handler(const boost::system::error_code& er) 
{ 
    std::cout << "Timer waited 5 sec" << std::endl; 
} 


void MyClass::read() 
{ 
    boost::asio::deadline_timer t(m_socket.get_io_service(),boost::posix_time::seconds(5)); 
    t.async_wait(boost::bind(&MyClass::read_handler,this,boost::asio::placeholders::error)); 
    m_socket.get_io_service().run();//Should make the io_service wait for all asynchronous tasks to finish 
    std::cout << "This message should be displayed after the wait" << std::endl; 
} 

void MyClass::connect_handler(const boost::system::error_code& error) 
{ 
    if(!error) 
    { 
     std::cout << "Connection done" << std::endl; 
     m_flag = 1; 
    } 
    else 
    { 
     std::cout << "Error in connection: " << error.message() << std::endl; 
    } 
} 


//connect method 
bool MyClass::connect(std::string const & host, uint16_t port) 
{ 
    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(host),port); 

    m_socket.async_connect(endpoint, 
      boost::bind(&MyClass::connect_handler, this, 
      boost::asio::placeholders::error)); 

    m_socket.get_io_service().run();//Wait async_connect and connect_handler to finish 

    if (m_flag == 0) return false; 
    else return true; 
} 


std::shared_ptr<MyClass> MyClass::create(std:: string const & host, uint16_t port) 
{ 
    boost::asio::io_service ios; 

    std::shared_ptr<MyClass> ptr(new MyClass(ios)); 

    bool bol = ptr->connect(host, port); 
    ptr->read(); 

    //while(1){} 

    if(bol == true) 
    { 
     //connection success, reading currently listening, pointer is returned to the user 
     return ptr; 
    } 
    else 
    { 
     //connection failure, pointer is still returned to the user but not listening as he's not connected 
     return ptr; 
    } 
} 

そして、私のメイン:私は私の問題を解決する方法を考え出し

#include <boost/date_time/posix_time/posix_time.hpp> 
#include <boost/asio.hpp> 
#include "MyClass.hpp" 

int main() 
{ 
    try 
    { 
    std::cout << "Creation of instance" << std::endl; 

    std::shared_ptr <MyClass> var = MyClass::create("127.0.0.1", 8301); 

    std::cout << "Instance created" << std::endl; 



    } 
    catch (std::exception& e) 
    { 
     std::cerr << e.what() << std::endl; 
    } 

    return 0; 
} 
+0

一時的な 'boost :: asio :: io_service'を' Run'や 'poll'を呼び出す前に破壊される' MyClass :: create'に作成しています。それを 'main'で作成し、' MyClass :: create'に渡してから 'run()'を呼び出してみてください。 – kenba

+0

@kenba明らかにあなたは正しいと思っていましたが、io_serviceのreset()も忘れてしまいました。私は彼を生かしておきます。 – PsykoBabar

+0

@PsykoBabarは、 'read()'で 'io_service :: run'を再度呼び出すことを意図しています。 ? 'io_service'を生かしたままにするには、@kenbaが示唆していることを実行するだけでなく、' connect_handler'から 'read()'を呼び出します。接続が成功した後、 'read()'が呼び出されます。今、 'read()'は、接続があるかどうかを呼び出す。私はこれがおそらくデバッグコードであり、 'read()'でソケットから読み込んでいないことを知っていますが、 'io_service'を'リセット 'して再度 'run'を呼び出す必要はありません。 – aichao

答えて

0

"create"メソッドの後にio_serviceが破壊されてしまったため、メインに返されたポインタは読み込みを続行できませんでした。 コールバックを起動するためにrun()を呼び出す必要がありましたが、メインで他の作業を続けたいと思ったので、メインではできませんでした。

私は分離されたスレッドを起動し、io_serviceを含むクラスを作成しました。そのスレッドはrun()を定期的に呼び出しています。その後、MyClassに属性として追加されました。

今、MyClassに起動された非同期タスクを停止しないMyClassへのポインタを返す「作成」呼び出しがあります。

関連する問題