Boost asio行为-从多个线程调用ios_service::run

boost asio behaviour - calling ios_service::run from multiple threads

本文关键字:ios 调用 service run 线程 行为 asio Boost      更新时间:2023-10-16

我正在尝试使用boost::asio截止时间定时器延迟函数调用如下

#include <boost/asio.hpp>
#include "boost/thread.hpp"
#include <iostream>
class MyTest {
public:
    MyTest()
    :_invokeCount(0),
     _handleCount(0)
    {}
    void handler(int i)
    {
        std::cout<<"ttHandled " <<i << std::endl;
        ++_handleCount;
    }
    void RunIOService()
    {
        std::cout<<"tStarted :"<< _invokeCount<< std::endl;
        _ios.run();
        std::cout<<"tFinished "<< _invokeCount << std::endl;
    }
    void invokeTimer()
    {
        std::cout<<"invoked " << ++_invokeCount << std::endl;
        boost::asio::deadline_timer t(_ios, boost::posix_time::milliseconds(5));
        t.async_wait(boost::bind(&MyTest::handler, this, _invokeCount));
        boost::thread th = boost::thread(boost::bind(&MyTest::RunIOService, this));
    }
    void PrintCount()
    {
        std::cout<<"Count = "<< _invokeCount << std::endl;
    }
    void Wait()
    {
        while (_invokeCount > _handleCount) {
            std::cout<<"X ";
            Sleep(1000);
        }
    }
private:
    int _invokeCount;
    int _handleCount;
    boost::asio::io_service _ios;
};
int main(int argc, char* argv[])
{
    MyTest test;
    for (int k=0; k<5; ++k) {
        test.invokeTimer();
        Sleep(40);
    }
    test.Wait();
    test.PrintCount();
    return EXIT_SUCCESS;
}

这个应用程序的输出不像我期望的那样:-

invoked 1
    Started :1
        Handled 1
    Finished 1
invoked 2
    Started :2
    Finished 2
invoked 3
    Started :3
        Handled 2
    Finished 3
invoked 4
    Started :4
        Handled 3
    Finished 4
invoked 5
    Started :5
        Handled 4
    Finished 5
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 

我期望在ios_service::run返回之前调用每个处理程序,并且从输出中似乎不是这样(在Started:2和Finished:2之间缺少输出)。而且,应用程序永远不会退出。也就是说,第五个处理程序永远不会被调用。

我错过了什么?

谢谢!

以下几点:

    你可能不需要5个线程。为什么不创建一个线程,并将事件触发到线程中运行的单个ioservice实例中呢?
  1. 尝试在线程运行函数中使用io_service::work,以在处理所有请求时保持io_service在作用域中。
  2. 当你的等待结束,停止你的io_service,加入你的线程,让你的程序退出
  3. 阅读这里关于io_service::work: http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/io_service.html

我在每次ios_service::run()之后添加了ios_service::reset(),效果如预期。

boost::asio::ioservice::reset()应该在后面一组run()调用之前调用。正如boost医生所说:此函数必须在run()、run_one()、poll()或poll_one()函数的任何第二组或更晚的调用之前调用,当由于io_service被停止或工作耗尽而返回之前调用这些函数时。这个函数允许io_service重置任何内部状态,比如一个"stopped"标志。

在run()、run_one()、poll()或poll_one()函数尚未调用时,不能调用该函数。