我试图使用boost :: asio :: io_service来实现ActiveObject,但结果并不完全符合我的预期:
以下是我的代码:
#include <boost/asio.hpp>
#include <chrono>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <memory>
#include <thread>
#include <string>
#include <functional>
#include <ctime>
#include <chrono>
#define SIZE 10
class ActiveObject
{
public:
ActiveObject()
{
executionThread_.reset( new std::thread( [&]{ service_.run(); } ) );
}
virtual ~ActiveObject()
{
// execute all unfinished work in case this object is leaving scope.
service_.poll();
service_.stop();
executionThread_->join();
std::cout << "active object thread exited" << std::endl;
}
void doSomething()
{
// post request the io_service to invoke someImpl method and return immediately
service_.post([=]{ someImpl();});
}
protected:
boost::asio::io_service service_;
private:
std::shared_ptr<std::thread> executionThread_;
void someImpl() {
std::chrono::milliseconds dura( 200 );
std::this_thread::sleep_for( dura );
std::cout << "poll thread id: " << std::this_thread::get_id() << std::endl;
}
};
int main()
{
std::cout << "main thread id: " << std::this_thread::get_id() << std::endl;
ActiveObject obj;
for(int i=0; i < SIZE; ++i) {
obj.doSomething(); // call is nonblocking
}
std::cout << "main thread exited " << std::endl;
return 0;
}
我想要的是在同一个线程上运行boost :: asio :: io_service :: run,但事实并非如此。从打印的日志中,run()也在主线程上运行。下面是打印的日志:
main thread id: 140070853244800
main thread exited
poll thread id: 140070832256768
poll thread id: 140070853244800
poll thread id: 140070832256768
poll thread id: 140070853244800
poll thread id: 140070832256768
poll thread id: 140070853244800
poll thread id: 140070853244800
poll thread id: 140070832256768
poll thread id: 140070853244800
poll thread id: 140070832256768
active object thread exited
对此有何想法?感谢
答案 0 :(得分:1)
至少在哪里
service_.poll();
service_.stop();
您正在积极地在活动线程上运行服务。
要缓解,您要说
service_.post([&] { service_.poll();});
service_.stop();
然后poll()
将是多余的。此出现以解决您的问题:
为什么我们甚至打电话给stop()
?所有工作完成后,run()
才会完成,对吧?事实上, run()
可能会在施工期间/之后立即完成。所有工作都将推迟到析构函数中。
但是,如果run()
完成,则需要重置服务(),因此实际上无法运行任务(demo live on Coliru !!!)哎呀。这是一个令人讨厌的竞争条件。
要防止run()
过早地完成&#34;,请使用work
项: Live On Coliru
#include <boost/asio.hpp>
#include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <chrono>
#include <ctime>
#include <functional>
#include <memory>
#include <string>
#include <thread>
#define SIZE 10
class ActiveObject
{
public:
ActiveObject()
: service_(),
work_(boost::asio::io_service::work(service_))
{
executionThread_.reset(new std::thread([&] { service_.run(); }));
}
virtual ~ActiveObject()
{
// execute all unfinished work in case this object is leaving scope.
work_ = boost::none;
executionThread_->join();
std::cout << "active object thread exited" << std::endl;
}
void doSomething()
{
// post request the io_service to invoke someImpl method and return immediately
service_.post([this] { someImpl();});
}
protected:
boost::asio::io_service service_;
boost::optional<boost::asio::io_service::work> work_;
private:
std::shared_ptr<std::thread> executionThread_;
void someImpl()
{
std::chrono::milliseconds dura(200);
std::this_thread::sleep_for(dura);
std::cout << "poll thread id: " << std::this_thread::get_id() << std::endl;
}
};
int main()
{
std::cout << "main thread id: " << std::this_thread::get_id() << std::endl;
ActiveObject obj;
std::chrono::milliseconds dura(200);
std::this_thread::sleep_for(dura);
for(int i=0; i < SIZE; ++i)
{
obj.doSomething(); // call is nonblocking
}
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "main thread exited " << std::endl;
}
输出:
main thread id: 140312603891520
poll thread id: 140312580617984
poll thread id: 140312580617984
poll thread id: 140312580617984
poll thread id: 140312580617984
main thread exited
poll thread id: 140312580617984
poll thread id: 140312580617984
poll thread id: 140312580617984
poll thread id: 140312580617984
poll thread id: 140312580617984
poll thread id: 140312580617984
active object thread exited