QT多线程和移动对象线程创建后

QT Multithreading and Moving Objects Threads after creation

本文关键字:线程 创建 对象 移动 多线程 QT      更新时间:2023-10-16

我有一个多线程程序,它从网站下载并获取信息,然后获取信息,创建一个对象,然后用图像将其添加到我的GridLayout中。

我有成千上万的对象,我需要创建,然后添加到我的网格布局,使用8个线程来获得信息,同样的8个线程然后创建对象,并将它们添加到8个不同的网格中。

程序运行大约20秒后,我得到一个
QThread::start:未能创建线程(访问代码无效。)错误。再过几秒钟,我得到了一些运行时C++错误,这些错误挂起并且不显示消息。这意味着什么?让我困惑的是,在这一点上,我的线程已经创建好了,而我实际上并没有创建更多的线程。。在这些线程中,尽管它们每个都在创建Widget对象,然后将它们发送到Main Gridlayout。。

我检查了我运行的线程数量(QThread:idealThreadCount),它只返回8个。

我是多线程从网站下载信息的,然后每条记录都会返回我创建的值到一个Object中,放入我的GridLayout中。

我在想,因为在这一点上,这些对象都属于单个线程,在所有url完成之前永远不会发出(finished()),所以它占用了一些东西并导致了这个错误?

在下载信息并将新对象添加到网格布局后,我是否应该尝试MoveToThread并将所有这些对象发送回主线程?

这些对正在发生的事情有意义吗?如果你想让我发布代码吗?

谢谢。

编辑:

只是在创作后尝试移动线程,但学会了QObject::moveToThread:小工具无法移动到新线程

这是我创建的线程

void checkNewArrivals::createWorkers(QString url, QString category, QString subCategory){
    QThread* thread = new QThread;
    checkNewArrivalWorker* worker = new checkNewArrivalWorker(url, category, subCategory);
    worker->moveToThread(thread);
    connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
    connect(thread, SIGNAL(started()), worker, SLOT(process()));
    connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
    connect(worker, SIGNAL(result(QString,QString,QString,QString,QString,int, int)), this, SLOT(addItem(QString,QString,QString,QString,QString,int, int)));
    connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    thread->start();
}

这是我的工人类函数,它会发出结果

void checkNewArrivalWorker::getHtml(QString url){
    html = QString::fromStdString(Curl->getWebsiteHtml(url.toStdString()));
    html = html.mid(html.indexOf("Goods List"));
    html = html.mid(0, html.indexOf("footer"));
    for (int i = 0; i < html.count("GoodsBox"); i++){
        //blah blah blah blah

        emit result(idLink, picLink, price, category, subCategory, row, col);
        col++;
        if (col == 5){
            col = 0;
            row++;
        }
        html = html.replace(itemRow, "");
    }
}

然后我添加结果来创建一个项目,并将其添加到网格布局中

void checkNewArrivals::addToGrid(QGridLayout *layout, QString id, QString picUrl, QString usPrice, int row, int col){
    checkNewArrivalItem* item = new checkNewArrivalItem;
    if (item->setupItem(id, picUrl, usPrice) == true){
        layout->addWidget(item, row, col);
    };
}

这些项目运行良好,直到我认为项目过载。。不太确定我为什么会出现这个错误。

Qt GUI对象不能存在于主线程之外的任何线程中。GUI对象需要在主线程中创建并添加到布局中。您仍然可以从后台线程收集数据,但需要将其传递回主线程进行显示。为此,我建议使用信号,因为默认情况下信号/插槽连接是线程安全的。

编辑:您的新线程看起来应该可以工作。然而,我认为您会发现最好保持特定数量的线程运行,并将工作委托给它们。首先,创建、启动、停止和销毁线程是一个昂贵的过程。但也许更重要的是,您可能只是创建了太多线程。

需要明确的是,QThread::idealThreadCount()不是您正在运行的线程数,而是您的CPU可以最有效地处理的线程数。我猜你有一个带超线程的四核CPU,它是8。

我认为很可能是您创建了太多线程。这听起来很像我错误地那样做的时候。