1

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

我需要创建数千个对象,然后将其添加到我的网格布局中,使用 8 个线程获取信息,然后使用相同的 8 个线程创建对象并将它们添加到 8 个不同的网格中。

程序运行大约 20 秒后,我收到
QThread::start: Failed to create thread (The access code is invalid.) 错误。又过了几秒钟,我得到一些运行时 C++ 错误,这些错误挂起并且不显示消息。这意味着什么?让我感到困惑的是,此时,我的线程已经创建并且我实际上并没有创建更多线程.. 在这些线程内部,尽管它们每个都在创建小部件对象,然后我将它们发送到主网格布局..

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

我正在使用多线程从站点下载信息,然后每个记录返回值,这些值我创建到对象中以放入我的 GridLayout。

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

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

这是否对正在发生的事情有意义,如果您希望我发布代码?

谢谢。

编辑:

刚尝试创建后移动线程,但得知 QObject::moveToThread: Widgets cannot be move to a new thread

这是我创建的线程

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);
    };
}

这些项目工作正常,直到我认为项目超载..不太确定我为什么会收到此错误。

4

1 回答 1

3

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

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

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

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

于 2013-02-02T21:07:45.670 回答