在我的多线程程序中,我经常使用如下所示的方法来同步对数据的访问:
class MyAsyncClass
{
public: // public thread safe interface of MyAsyncClass
void start()
{
// add work to io_service
_ioServiceWork.reset(new boost::asio::io_service::work(_ioService));
// start io service
_ioServiceThread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&boost::asio::io_service::run, &_ioService)));
}
void stop()
{
_ioService.post(boost::bind(&MyAsyncClass::stop_internal, this));
// QUESTION:
// how do I wait for stop_internal to finish here?
// remove work
_ioServiceWork.reset();
// wait for the io_service to return from run()
if (_ioServiceThread && _ioServiceThread->joinable())
_ioServiceThread->join();
// allow subsequent calls to run()
_ioService.reset();
// delete thread
_ioServiceThread.reset();
}
void doSometing()
{
_ioService.post(boost::bind(&MyAsyncClass::doSometing_internal, this));
}
private: // internal handlers
void stop_internal()
{
_myMember = 0;
}
void doSomething_internal()
{
_myMember++;
}
private: // private variables
// io service and its thread
boost::asio::io_service _ioService;
boost::shared_ptr<boost::thread> _ioServiceThread;
// work object to prevent io service from running out of work
std::unique_ptr<boost::asio::io_service::work> _ioServiceWork;
// some member that should be modified only from _ioServiceThread
int _myMember;
};
这个类的公共(public)接口(interface)是线程安全的,因为它的公共(public)方法可以从任何线程调用,boost::asio::io_service
负责访问私有(private)成员这个类是同步的。因此,public doSomething()
除了将实际工作发布到 io_service
之外什么都不做。
MyAsyncClass
的start()
和stop()
方法显然在MyAsyncClass
中开始和停止处理。我希望能够从任何线程调用 MyAsyncClass::stop()
并且它不应在 MyAsyncClass
的未初始化完成之前返回。
由于在这种特殊情况下我需要在停止时修改我的一个私有(private)成员(需要同步访问),我引入了一个 stop_internal()
方法,我将其发布到 io_service
来自 stop()
。
现在的问题是:如何在 stop()
中等待 stop_internal()
的执行完成?请注意,我不能直接调用 stop_internal()
,因为它会在错误的线程中运行。
编辑:
如果 MyAsyncClass::stop()
是从 _ioServiceThread
调用的,那么最好有一个解决方案,这样 MyAsyncClass
也可以自行停止。
最佳答案
我刚刚自己找到了一个非常好的解决方案:
我没有在 stop()
中删除工作(重置 _ioServiceWork
),而是在 stop_internal()
结束时执行此操作。这意味着 _ioServiceThread->join()
会阻塞,直到 stop_internal()
完成 - 这正是我想要的。
这个解决方案的优点在于它不需要任何互斥量或条件变量或类似的东西。
关于c++ - 等待异步方法完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22665677/