2016-04-04 3 views
0

QThreadのサブクラス化が悪い考えであり、QThreadを適切に使用して、moveToThreadメソッドを呼び出す理由について、多くの記事を読んだことがあります。 Hereこのような設計の典型的な例を見ることができます。QThreadオブジェクトをワーカークラスのメンバとして

私は、次の要件を満たす必要が設計していますクラス:

  • それはシグナルとスロットを使いたいので、私はイベントループが必要になりますし、moveToThreadを使用します。

  • 信号とスロットのみのインターフェイスが公開されます。通常のC++メソッドはありません。

  • すべてのスロットは、オブジェクトの専用スレッドで実行する必要があります。オブジェクトごとに1スレッドです。したがって、オブジェクトが作成されるとスレッドが作成され、オブジェクトが終了すると終了する必要があります。

このように明らかな解決策は、(ちょうどスケッチコードをテストしていません)頭に浮かぶ:だからポイントは、労働者階級の(プライベート)メンバーとしてQThreadオブジェクトを宣言することです

class Worker : public QObject { 
Q_OBJECT 

public: 
    Worker() { 
     thread = new QThread(); 
     // ...Some signal-slot connections may be done here... 
     // ...Some other connections may be performed by user code... 
     moveToThread(thread); 
     thread->start(); 
    } 

    ~Worker() { 
     thread->exit(); 
     thread->wait(); 
     delete thread; 
    } 

public slots: 
    void process(); // and other interface slots 

signals: 
    // Interface signals 

private: 
    QThread* thread; 
}; 

が、どのような例や他の人々のコードでもこれまでに見たことはありません。

だから私はこのデザインに欠陥があるのだろうか?私に気づかなかったいくつかの致命的な欠点がありますか?それとも大丈夫ですが、しばしば必要とされることはありませんか?

+0

まず、(unique_ptrなど)のようなRAIIオブジェクトを使用します。第二に、これはおそらくCodeReview SEサイトに適しています。 – OMGtechy

+1

@OMGtechyこれはコードレビューではおそらく閉じられているだろう、著者は "テストされていない、単なるスケッチコード" _と書いてある。コードレビューには実際の作業コードが必要です。参考までに[on-topic](http://codereview.stackexchange.com/help/on-topic)を参照してください。 – Phrancis

+1

@Phrancisああ、その場合は、最初に@Sergeyを持って行くことをお勧めします! – OMGtechy

答えて

1

これは、オブジェクトをワーカースレッドから移動する限り可能です。ここでは、あなたがそれを行う方法です - スレッドを値で保持する必要があることに注意してください。コンパイラを使用してメモリを管理しないことには意味がありません。仕事がQtConcurrent::runを経由して非同期的に行うことができることを考えると

class Worker : public QObject { 
    Q_OBJECT 
    QThread m_thread; 
public: 
    Worker() { 
    m_thread.start(); 
    moveToThread(&m_thread); 
    } 
    ~Worker() { 
    // Move us out of any thread. 
    // moveToThread must always be called from QObject::thread()! 
    { 
     QObject sig; 
     sig.connect(&sig, &QObject::destroyed, this, [this]{ 
     this->moveToThread(0); // become thread-less 
     m_thread->quit(); 
     }); 
    } 
    // Wait for the thread to stop 
    m_thread.wait(); 
    } 
}; 

、それはあなたが、とにかくそのようなオブジェクトを使用してはならないことを、かなり可能です。ほとんどの場合、アイドル状態のスレッドは無駄になります。なぜなら、スレッドを常に実行可能にすることはほとんどできないからです。実行不能なスレッドは基本的に無駄なリソースです。

+0

私はこのコードが何もしないと仮定します: 'QThread * curThread = thread(); this-> moveToThread(curThread); '。また、デストラクタでそのスレッドを変えるトリックをする必要はないと私は考えます。どのスレッドがオブジェクトを破壊するかは実際問題ではありません。 – hank

+0

@hankデストラクター呼び出しスレッドはm_threadによって処理されるスレッドであることが保証されていないので、コードが必要であると思います。公式の文書(http://doc.qt.io/qt-5/threads-qobject.html)では、「オブジェクトを所有しているスレッド以外のスレッドからQObjectで削除を呼び出す(または他の方法でオブジェクトにアクセスする) )危険です... "。 – Sergey

+0

@Sergey "...オブジェクトがその時点でイベントを処理していないことを保証しない限り、安全ではありません"。スレッドを終了して停止すると、オブジェクトはイベントを処理しません。 – hank

関連する問題