等待异步方法完成

时间:2014-03-26 15:25:18

标签: c++ boost-asio

在我的多线程程序中,我经常使用如下所示的方法来同步对数据的访问:

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;

};

这个类的公共接口是线程安全的,因为它的公共方法可以从任何线程调用,boost::asio::io_service注意对这个类的私有成员的访问是同步的。因此,公众doSomething()只会将实际工作发布到io_service

start()的{​​{1}}和stop()方法显然会在MyAsyncClass中开始和停止处理。我希望能够从任何线程调用MyAsyncClass,并且在MyAsyncClass::stop()的未初始化完成之前它不应该返回。

由于在这种特殊情况下我需要在停止时修改我的一个私有成员(需要同步访问),我介绍了MyAsyncClass方法,我从stop_internal()发布到io_service }。

现在的问题是:我如何等待stop()执行内部stop_internal()?请注意,我无法直接调用stop(),因为它会在错误的线程中运行。

修改

如果从stop_internal()调用MyAsyncClass::stop(),那么有一个解决方案也很有用,这样_ioServiceThread也可以自行停止。

1 个答案:

答案 0 :(得分:1)

我自己找到了一个非常好的解决方案:

我没有在_ioServiceWork删除工作(重置stop()),而是在stop_internal()结束时执行此操作。这意味着_ioServiceThread->join()阻止stop_internal()完成 - 正是我想要的。

这个解决方案的好处是它不需要任何互斥或条件变量或类似的东西。