在boost :: thread_group中称为成员函数的参数指示为null

Pointer given as parameter to member function called in boost::thread_group is null

本文关键字:函数 成员 指示 null 参数 thread boost group      更新时间:2023-10-16

我正在使用带有C 的线索和boost :: thread_group,但在线程中称为方法'widgetProcessorjob'获取null参数(widget)。我试图以不同的方式做到这一点,我认为我使用的是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();
}
// 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()时,您正在"联系"与发布给所有处理程序的相同记录集。

现在,根据您的线程执行时间和不同的种族条件的时间,您可能已经到达记录集的末端,甚至在任何处理程序都被召唤之前,即使不是这样,您也处于种族条件下充其量只能让您想要的一部分。

我以为我很难使用boost :: asio!发布后,我尝试了我的程序,而没有无限循环"可用",并且使用ioservice进行了无限循环的作业,因为我从未称呼停止方法。为了获得正确的答案,我移动了thread_pool&amp;io_service声明/定义在"可用"循环中,并在每次迭代中进行呼叫停止!这是正确的答案,包括@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();
}