2

並列計算に使えるワーカークラスを考えていました。

オブジェクトを作成した後、ワーカーを別のスレッドに明示的に移動する必要がある状況を回避したかったのです。

Worker worker;
QThread thread;
worker.moveToThread(&thread);
thread.start();
worker.start();

これは私が思いついた解決策です:

ヘッダ:

#include <QObject>
#include <QThread>

class ThreadedWorker : public QObject
{
    Q_OBJECT
public:
    explicit ThreadedWorker(QObject *parent = 0);
signals:
    void finished(ThreadedWorker* worker);
public slots:
    void start();
protected:
    virtual void run();
    QThread workerThread_;
    bool isRunning_;
};

ソース:

#include "threadedworker.h"

ThreadedWorker::ThreadedWorker(QObject *parent) : QObject(parent)
{
    this->moveToThread(&this->workerThread_);
    this->workerThread_.start();
    this->isRunning_ = false;
}

void ThreadedWorker::start()
{
    if(!this->isRunning_)
     {
         this->isRunning_ = true;
         this->run();
     }
 }

 void ThreadedWorker::run()
 {
     // HERE GOES THE ACTUAL WORK FOR THE WORKER
     //
     //
     emit this->finished(this); // added to inform a controller object that the worker has finished
   }

Zailborg によるコメントの後に更新:

だから今私はただ作成します:

ThreadedWorker worker1;
ThreadedWorker worker2;

外部信号によってスロットを呼び出し、それらstart()は並行して実行されます。

QThread workerThread_ただし、私の主な関心事は、クラスのメンバーとして配置しThreadedWorker、オブジェクトをコンストラクターでそのスレッドに移動することが悪い習慣ではないかどうかです。

4

3 に答える 3

3

QThread workerThread_ を ThreadedWorker クラスのメンバーとして配置するのが悪い習慣ではないかどうか

オブジェクトがそのスレッドに移動されると、オブジェクトとその子が移動されます。子は、親を QObject 派生クラスのコンストラクターに渡すか、setParent を呼び出すときに、Qt の親子階層でリンクされたオブジェクトです。

QThreadポインターなどのメンバー ポインターの場合、それはクラスの「子」ではありません。したがって、ThreadedWorker オブジェクトを新しいスレッドに移動すると、これが機能します。ただし、スレッド アフィニティの混乱により、問題が発生する可能性があります。メイン オブジェクトは新しいスレッドに移動されますが、スレッド アフィニティが異なるオブジェクトへのメンバー ポインターを保持します。QThread* が指すオブジェクト。

質問に示されているコードは、QThread ポインターではなく、QThread インスタンスを参照しています。これを念頭に置いて、次の場合のQObject::moveToThreadのドキュメントを検討してください。

警告:この関数はスレッドセーフではありません。現在のスレッドは、現在のスレッド アフィニティと同じでなければなりません。つまり、この関数は現在のスレッドから別のスレッドにオブジェクトを「プッシュ」することしかできず、任意のスレッドから現在のスレッドにオブジェクトを「プル」することはできません。

したがって、QThread と QObject::moveToThread の設計では、QThread の親和性が安定しており、変更されないことが想定されているのではないかと思います。移動されるオブジェクトのメンバーであるため、これは当てはまりません。

このため、QThread インスタンスを QObject のメンバーとして持ち、そのオブジェクトをそのスレッドに移動することはお勧めできません。

QThread を使用する場合は、QThreadを実際に使用する方法で概説されている方法を読んで、それに従うことをお勧めします。

さらに、moveToThread の機能によって QThread と QObject の 1 対多の関係が可能になることは見過ごされがちです。そのため、QThread オブジェクトを作成して複数の QObject インスタンスを新しいスレッドに移動することはまったく問題ありません。また、通常、使用可能なプロセッサ コアよりも多くのスレッドを作成しても、ほとんどメリットはありません。

于 2014-11-18T14:25:37.913 に答える