我正在使用带有C ++和boost :: thread_group的线程池,但在线程中调用方法'widgetProcessorJob'获取一个空参数(小部件)。 我尝试以不同的方式制作它,我认为我正在使用boost :: asio严重... 我正在寻找一个可以告诉我我做错了什么以及哪种方式最好的方法?
void MarketingAutomation::processOnWidgets() {
boost::asio::io_service ioService;
boost::thread_group threadpool;
bool available = true; // need infinite loop in my program
int offset = 0; // Only for batching
boost::asio::io_service::work work(ioService);
for (int i = 0; i < _poolSize; i++) {
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioService));
}
while (available) {
std::shared_ptr<sql::ResultSet> widgets(MyDBConnector::getInstance().getWidgets(_batchSize, offset)); // just getting some data from sql base with mysqlcppconn
if (!widgets->next()) {
offset = 0;
Logger::getInstance().logSTD("Restart widgets iteration !"); // this part is called when i did stuff on all batches
} else {
Logger::getInstance().logSTD("Proccess on " + std::to_string((offset / _batchSize) + 1) + " batch");
// loop through the batch
while (!widgets->isAfterLast()) {
ioService.post(boost::bind(&MarketingAutomation::widgetProcessorJob, this, widgets));
widgets->next();
}
threadpool.join_all();
Logger::getInstance().logSTD("Finish on " + std::to_string((offset / _batchSize) + 1) + " batch");
offset += _batchSize;
}
}
}
// Here is the function called in thread
void MarketingAutomation::widgetProcessorJob(std::shared_ptr<sql::ResultSet> widget) {
WidgetProcessor widgetProcessor(widget, _kind); // Here widget is already null, but why ? :'(
widgetProcessor.processOnWidget();
}
答案 0 :(得分:1)
// loop through the batch
while (!widgets->isAfterLast()) {
ioService.post(boost::bind(&MarketingAutomation::widgetProcessorJob, this, widgets));
widgets->next();
}
您只有一个std::shared_ptr<sql::ResultSet> widgets
。通过多次发布它来制作智能指针的副本,但所有这些智能指针都指向相同的基础sql::ResultSet
。
这意味着当你致电next()
时,你正在&#34; nexting&#34;您发布给所有处理程序的记录集。
现在,根据线程的执行时间和不同的竞争条件,你甚至可以在任何处理程序被调用之前到达记录集的末尾,即使不是这种情况,你也处于竞争条件会让你充其量只是你想要的一部分。
答案 1 :(得分:1)
正如我以为我使用了boost :: asio!发布后我尝试了我的程序,没有无限循环'可用',并且使用ioService运行的作业进行了无限循环,因为我从未调用过stop方法。为了得到正确答案,我移动了thread_pool&amp; 'available'循环中的io_service声明/定义,并在每次迭代时调用stop!这是正确的答案,包括@Drax答案:
void MarketingAutomation::processOnWidgets() {
bool available = true;
int offset = 0;
while (available) {
std::shared_ptr<sql::ResultSet> widgets(SlaaskDBConnector::getInstance().getWidgets(_batchSize, offset));
if (!widgets->next()) {
offset = 0;
Logger::getInstance().logSTD("Restart widgets iteration !");
} else {
boost::asio::io_service ioService;
boost::thread_group threadpool;
boost::asio::io_service::work work(ioService);
for (int i = 0; i < _poolSize; i++) {
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioService));
}
Logger::getInstance().logSTD("Proccess on " + std::to_string((offset / _batchSize) + 1) + " batch");
while (!widgets->isAfterLast()) {
ioService.post(boost::bind(&MarketingAutomation::widgetProcessorJob, this, widgets->getInt("id")));
widgets->next();
}
ioService.stop();
threadpool.join_all();
Logger::getInstance().logSTD("Finish on " + std::to_string((offset / _batchSize) + 1) + " batch");
offset += _batchSize;
}
}
}
void MarketingAutomation::widgetProcessorJob(int widgetID) {
WidgetProcessor widgetProcessor(widgetID, _kind); // Here widget is already null, but why ? :'(
widgetProcessor.processOnWidget();
}