1

Webサイトから情報をダウンロードして取得し、その情報を取得してオブジェクトを作成し、それを画像とともにGridLayoutに追加するマルチスレッドプログラムがあります。

何千ものオブジェクトを作成してグリッドレイアウトに追加し、8つのスレッドを使用して情報を取得し、同じ8つのスレッドでオブジェクトを作成して8つの異なるグリッドに追加します。

プログラムを約20秒間実行すると、
QThread :: start:スレッドの作成に失敗しました(アクセスコードが無効です)というエラーが表示されます。さらに数秒後、ハングしてメッセージを表示しないランタイムC++エラーが発生します。これはどういう意味ですか?私を混乱させているのは、この時点で、私のスレッドはすでに作成されており、実際にはそれ以上のスレッドを作成していないということです。スレッドはそれぞれウィジェットオブジェクトを作成し、メイングリッドレイアウトに送信しています。

実行しているスレッドの量(QThread:idealThreadCount)を確認したところ、8つしか返されませんでした。

サイトから情報をダウンロードするためにマルチスレッド化しています。その後、各レコードは、GridLayoutに配置するオブジェクトに作成した値を返します。

その時点で、これらのオブジェクトはすべて単一のスレッドに属し、すべてのURLが完了するまでemit(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();
}

これが結果を出す私のworkerクラス関数です

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オブジェクトを作成し、メインスレッドのレイアウトに追加する必要があります。バックグラウンドスレッドからデータを収集することはできますが、表示するためにメインスレッドに戻す必要があります。そのためには、シグナル/スロット接続はデフォルトでスレッドセーフであるため、シグナルを使用することをお勧めします。

編集:新しいスレッドは機能するはずです。ただし、特定の数のスレッドを実行し続け、作業をそれらに委任することが望ましいと思います。1つは、スレッドの作成、開始、停止、および破棄はコストのかかるプロセスです。しかし、もっと重要なのは、おそらく、作成しているスレッドが多すぎる可能性があるということです。

明確にするために、QThread :: IdealThreadCount()は、実行しているスレッドの数ではなく、CPUが最も効率的に処理できるスレッドの数です。ハイパースレッディングを備えたクアッドコアCPUを使用していると思いますが、これは8になります。

作成しているスレッドが多すぎる可能性が高いと思います。これは、私が誤ってそれをしたときのように聞こえます。

于 2013-02-02T21:07:45.670 に答える