简体   繁体   English

的boost :: ASIO。 确保仅在调用async_receive(...)之后才调用io_service.run()?

[英]BOOST::ASIO. Making sure io_service.run() is invoked only after async_receive(…) is called?

I have a problem where two threads are called like this, one after another. 我有一个问题,两个这样的线程一个接一个地调用。

new boost::thread( &SERVER::start_receive, this);

new boost::thread( &SERVER::run_io_service, this);

Where the first thread calls this function. 第一个线程在哪里调用此函数。

void start_receive()
{   
    udp_socket.async_receive(....);
}

and the second thread calls, 第二个线程调用

void run_io_service()
{  
    io_service.run();
}

and sometimes the io_service thread ends up finishing before the start_receive() thread and then the server cannot receive packets. 有时io_service线程在start_receive()线程之前结束工作,然后服务器无法接收数据包。

I thought about putting a sleep function between the two threads to wait a while for the start_receive() to complete and that works but I wondered if there was another sure fire way to make this happen? 我曾考虑过在两个线程之间放置一个sleep函数,等待一会儿,以便start_receive()完成并且可以工作,但我想知道是否还有另一种可靠的方法可以实现这一目标?

If you want to keep the io_service running, create a work object: 如果要保持io_service运行,请创建一个work对象:

boost::asio::io_service svc;
auto work = std::make_shared<boost::asio::io_service::work>(svc);
svc.run(); // this will block as long as the work object is valid.

The nice thing about this approach is that the work object above will keep the svc object "running", but not block any other operations on it. 这种方法的svc是,上面的work对象将使svc对象保持“运行”状态,但不会阻止对其进行任何其他操作。

When you call io_service.run() , the thread will block, dispatching posted handlers until either: 当您调用io_service.run() ,线程将阻塞,分派已发布的处理程序,直到发生以下任何一种情况:

  1. There are no io_service::work objects associated with the io_service , or 没有与io_service关联的io_service::work对象,或者

  2. io_service.stop() is called. io_service.stop()被调用。

If either of these happens, the io_service enters the stopped state and will refuse to dispatch any more handlers in future until its reset() method is called. 如果这两种情况之一发生, io_service将进入停止状态,并且以后将拒绝分派任何其他处理程序,直到调用其reset()方法为止。

Every time you initiate an asynchronous operation on an io object associated with the io_service, an io_service::work object is embedded in the asynchronous handler. 每次对与io_service关联的io对象启动异步操作时,都会在异步处理程序中嵌入io_service :: work对象。

For this reason, point (1) above cannot happen until the asynchronous handler has run. 因此,在异步处理程序运行之前,上面的点(1)不会发生。

this code therefore will guarantee that the async process completes and that the asserts pass: 因此,此代码将确保异步过程完成并且断言通过:

asio::io_service ios;    // ios is not in stopped state
assert(!ios.stopped());
auto obj = some_io_object(ios);
bool completed = false;
obj.async_something(..., [&](auto const& ec) { completed = true; });
// nothing will happen yet. There is now 1 work object associated with ios
assert(!completed);

auto ran = ios.run();
assert(completed);
assert(ran == 1);    // only 1 async op waiting for completion.
assert(ios.stopped());  // io_service is exhausted and no work remaining

ios.reset();
assert(!ios.stopped());  // io_service is ready to run again 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM