在结构中创建绑定到 io_service 的线程
Creating thread bound to io_service inside a struct
我正在尝试创建一个包含 boost::thread 对象的简单结构。该结构(ApplicationPair)的构造函数需要传递一个 io_service 引用对象和一个方法;现在,为简单起见,我使用不带参数的 void 方法。
之后,使用 boost::bind.
创建线程
ApplicationPair.h
#ifndef APPLICATIONPAIR_H
#define APPLICATIONPAIR_H
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <cstdarg>
template<typename T>
struct ApplicationPair
{
ApplicationPair(boost::asio::io_service& iSvc, boost::function<T()> func ) : _func(func)
{
iSvc.post(boost::bind(&ApplicationPair<T>::run, this));
thr = boost::thread(boost::bind(&boost::asio::io_service::run, &iSvc));
}
ApplicationPair() = delete;
~ApplicationPair() { if (thr.joinable()) thr.join(); }
void run();
boost::thread thr;
boost::function<T()> _func;
};
#endif
这里的想法是,我创建的每个新 ApplicationPair 对象在 io_service 上都有自己的线程,并且会在实例化时启动我想要的任何方法。
主要内容如下:
main.cpp
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <cstdio>
boost::asio::io_service iSvc;
void HelloWorld()
{
std::cout << "HelloWorld\n";
}
template<typename T>
void ApplicationPair<T>::run()
{
this->_func();
}
int main()
{
ApplicationPair<void> p1(boost::ref(iSvc), HelloWorld);
ApplicationPair<void> p2(boost::ref(iSvc), HelloWorld);
ApplicationPair<void> p3(boost::ref(iSvc), HelloWorld);
return 0;
}
这就是我意识到事情进展得很糟糕的地方:我的预期输出是 3 "HelloWorld" 打印,但我只得到 2。
更奇怪的是,如果我 运行 调试,并按指令继续进一步的指令,HelloWorld 只打印一次!
老实说我一无所知,但我很清楚我没有完全理解多线程和 io_services 是如何工作的,Boost.org 上的文档根本没有帮助。
正如您怀疑的那样,您遗漏了有关 ASIO 的一些关键点。
您声明希望每个 ApplicationPair 在 io_service 上都有自己的线程。这实际上不是它的工作原理。在线程上调用 io_service.run() 后,该线程现在由 io_service 拥有。 io_service 将按其认为合适的方式安排活动。
把它想象成一个线程池,你 post 任务到 io_service 并且它将它们调度到池中。
另外,你应该看看 strands。这就像互斥体的 ASIO 版本。它的功能相似,但在概念上有所不同。boost::asio strand example
这在这里似乎并不重要,因为您不是在读取或写入变量,但是 std::cout 是您必须管理的全局资源。
我试图重新编写你的代码来给你举个例子,但这些差异将极大地改变它。而且我不确定您的最终目标是什么,因此很难提供示例。
还有一些不错的 youtube 视频:
asio::strand
asio basics
我正在尝试创建一个包含 boost::thread 对象的简单结构。该结构(ApplicationPair)的构造函数需要传递一个 io_service 引用对象和一个方法;现在,为简单起见,我使用不带参数的 void 方法。 之后,使用 boost::bind.
创建线程ApplicationPair.h
#ifndef APPLICATIONPAIR_H
#define APPLICATIONPAIR_H
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <cstdarg>
template<typename T>
struct ApplicationPair
{
ApplicationPair(boost::asio::io_service& iSvc, boost::function<T()> func ) : _func(func)
{
iSvc.post(boost::bind(&ApplicationPair<T>::run, this));
thr = boost::thread(boost::bind(&boost::asio::io_service::run, &iSvc));
}
ApplicationPair() = delete;
~ApplicationPair() { if (thr.joinable()) thr.join(); }
void run();
boost::thread thr;
boost::function<T()> _func;
};
#endif
这里的想法是,我创建的每个新 ApplicationPair 对象在 io_service 上都有自己的线程,并且会在实例化时启动我想要的任何方法。
主要内容如下:
main.cpp
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <cstdio>
boost::asio::io_service iSvc;
void HelloWorld()
{
std::cout << "HelloWorld\n";
}
template<typename T>
void ApplicationPair<T>::run()
{
this->_func();
}
int main()
{
ApplicationPair<void> p1(boost::ref(iSvc), HelloWorld);
ApplicationPair<void> p2(boost::ref(iSvc), HelloWorld);
ApplicationPair<void> p3(boost::ref(iSvc), HelloWorld);
return 0;
}
这就是我意识到事情进展得很糟糕的地方:我的预期输出是 3 "HelloWorld" 打印,但我只得到 2。 更奇怪的是,如果我 运行 调试,并按指令继续进一步的指令,HelloWorld 只打印一次!
老实说我一无所知,但我很清楚我没有完全理解多线程和 io_services 是如何工作的,Boost.org 上的文档根本没有帮助。
正如您怀疑的那样,您遗漏了有关 ASIO 的一些关键点。
您声明希望每个 ApplicationPair 在 io_service 上都有自己的线程。这实际上不是它的工作原理。在线程上调用 io_service.run() 后,该线程现在由 io_service 拥有。 io_service 将按其认为合适的方式安排活动。
把它想象成一个线程池,你 post 任务到 io_service 并且它将它们调度到池中。
另外,你应该看看 strands。这就像互斥体的 ASIO 版本。它的功能相似,但在概念上有所不同。boost::asio strand example
这在这里似乎并不重要,因为您不是在读取或写入变量,但是 std::cout 是您必须管理的全局资源。
我试图重新编写你的代码来给你举个例子,但这些差异将极大地改变它。而且我不确定您的最终目标是什么,因此很难提供示例。
还有一些不错的 youtube 视频: asio::strand asio basics