2016-03-04 84 views
0

我正在使用boost::asio來建立一個異步客戶端通信類。可以提升:asio io_service.run()在循環中不止一次調用?

在我的設計中,我有一個類(AsioThread)和一個作爲獨立線程啓動的主運行方法。這裏是類方法代碼:

void AsioThread::Run() 
    { 
     while (true) 
     { 
      transactionMutex.lock(); 

      switch (asioState) 
      { 
       case (AsioStateType::Connect): // Start a connection 
       { 
        std::string address = currentCommand.arguments["address"]; 
        std::string port = currentCommand.arguments["port"]; 

        asioState = AsioStateType::ConnectWait; 

        boost::asio::ip::tcp::resolver::iterator end; 

        if (currentEndPoints == end) 
        { 
         boost::asio::io_service ios; 
         boost::asio::ip::tcp::resolver resolver(ios); 
         boost::asio::ip::tcp::resolver::query query(address, port); 
         currentEndPoints = resolver.resolve(query); 
        } 
        else 
        { 
         currentEndPoints++; 
        } 

        currentSocket->close(); 
        currentSocket->async_connect(*currentEndPoints, boost::bind(&AsioThread::ConnectHandler, this, _1));  
        break; 
       } 

       case (AsioStateType::ConnectResponse): // Receive connection welcome message 
       { 
        asioState = AsioStateType::ConnectResponseWait; 
        currentSocket->async_receive(boost::asio::buffer(boost::asio::buffer(rxBuffer, MAX_BUFFER_SIZE)), 0, boost::bind(&AsioThread::ReceiveDataHandler, this, _1, _2)); 
        break; 
       } 
      } 

      transactionMutex.unlock(); 

      ioService.run(); 
      std::this_thread::sleep_for(std::chrono::milliseconds(100)); 
     } 
    } 

有了這段代碼,回調函數永遠不會被調用。如果我將ioService.run()放在async_connect或async_receive行之後,則會調用它來進行連接 - 而不是接收消息。另外,如果我添加調試線,如:

`std::cout << "I´m here " << std::endl´ 

有時回調是所謂的,這取決於我把這個調試代碼的地方。

對我來說,我錯了,使用ioService.run()。請注意,每次循環傳遞都會調用它(每秒10次)。

互斥量用於控制其他線程對asioState的寫入訪問 - 其他線程通過使用此成員變量傳遞的消息來命令此主循環操作。

幫助表示讚賞找到出路what's錯在這裏...

+0

這不是使用asio的方式。閱讀文檔中的示例。 http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/example/cpp03/http/client/async_client.cpp –

+0

你的意思是隻有一種方法可以使用asio? – Mendes

+0

不,有幾種方法,但是從線程或線程池中爲io服務提供服務是使用它的特定方式,並且存在正確的習慣用法。您需要創建一個工作對象以防止io服務停止。當您希望工作線程停止時,請在io服務上調用stop()。 –

回答

1

io_service::run()用完的工作,它返回。在異步操作之後調用ioService.run()時發生的情況是,它允許該操作完成,然後耗盡工作並返回。排隊下一個操作後,您需要運行到io_service以處理操作。

另一種方法是在提交boost::io_service::work對象以保持活動狀態後,讓線程運行ioService::run()。要處理switch語句中的情況,您可以使用io_service::post()觸發操作,以便在運行處理程序內運行它們而不是輪詢狀態變量。當你想關閉線程時,銷燬工作對象。

+0

我沒有得到你說的那句話:「在將下一個操作排隊後,你需要運行io_service來處理操作。」我在每次交互時調用ioService.run()... – Mendes

+0

如果io_service耗盡工作,它將處於「stopped()」狀態。你需要「重置()」來讓它在你完成一些工作後再做更多的工作。 –

相關問題