可以提升:asio io_service.run()在循环中被多次调用?

时间:2016-03-04 22:29:21

标签: c++ multithreading boost boost-asio

我正在使用boost::asio构建异步客户端通信类。

在我的设计中,我有一个类(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));
        }
    }

使用此代码,永远不会调用回调。如果我在async_connect或async_receive行之后放置ioService.run(),则会调用它来进行连接 - 而不是用于消息接收。如果我添加调试行,如:

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

有时会调用回调,具体取决于我放置此调试代码的位置。

对我来说,使用ioService.run()我错了。请注意,每次循环传递都会调用它(每秒10次)。

互斥锁用于控制其他线程对asioState的写访问权限 - 其他线程通过使用此成员变量传递的消息来命令此主循环操作。

帮助感谢在这里找出错误的方法...

1 个答案:

答案 0 :(得分:1)

io_service::run()用尽时,它会返回。在异步操作之后调用ioService.run()时发生的事情是它允许该操作完成,然后用完并返回。排队下一个操作后,需要运行到io_service来处理操作。

另一种方法是在提交ioService::run()对象后让一个只运行boost::io_service::work的线程使其保持活动状态。要处理switch语句中的情况,可以使用io_service::post()触发操作以在运行处理程序内运行它们,而不是轮询状态变量。如果要关闭线程,请销毁工作对象。