2017-03-31 27 views
1

私は、コピーせずに一部のワーカースレッドからクライアントに結果データを渡す方法について考えています。 Workerは他のスレッドで動作し、BigDataはQObjectを継承します。私の考えはデータの所有権を変更することです:QThread結果データをMainThreadに渡します

class Worker: public QObject 
{ 
    Q_OBJECT 
public: 
    explicit Worker(QObject *parent = 0): QObject(parent); 
signals: 
    void resultReady(BigData *data); 
public slots: 
    void doWork() { 
     BigData *data = new BigData(this); // alloc new Data 
     while (!dataReady) { 
      ... // appending data 
     } 
     // Data ready 
     // clearing ownership 
     data->setParent(NULL); // data can't be moved to another thread with parent 
     data->moveToThread(NULL); 
     emit resultReady(data); 
    } 
}; 

void MainWindow::handleResult(BigData *data) 
{ 
    if (currentData_) { 
     delete currentData_; 
    } 
    data->setParent(this); // set new ownership 

    // works only if data's thread is NULL 
    data->moveToThread(QApplication::instance()->thread()); 
    currentData_ = data; 
} 

いいですか?それとももっと適切な方法がありますか?

+0

'BigData'クラスが' QObject'を継承する理由はありますか?それはそれ自身のシグナル/スロットを持っていますか? – Mike

+0

いいえ、私はちょうどQObjectを使用しています。それは、親破壊の自動破壊BigDataが便利だからです。 – Sorcerer

答えて

2

は、通常は1つのスレッドから別の​​にプッシュオブジェクトを使用します。これは、doWork()スロットにdata->moveToThread(NULL);を実行する代わりにdata->moveToThread(QApplication::instance()->thread());と書くと、スレッドアフィニティをNULLに設定してメインスレッドから変更しないようにできます。しかし、BigDataインスタンスをメインスレッドに移動した後、ワーカースレッドからQObjectに触れていることに注意してください。オブジェクトのすべてのアクティブなタイマーがリセットされることを

注:について注意するもう一つは、スレッド間で前後QObjectを移動するdocsから、いくつかの副作用を引き起こす可能性がある、ということです。タイマーは、現在のスレッドで最初に停止され、targetThreadで(同じ間隔で)再開されます。その結果、スレッド間でオブジェクトを絶えず動かすと、タイマーイベントが無期限に延期される可能性があります。ちょうどメモリ管理の目的のためにQObjectをInherting

はやり過ぎです。 QObjectは、実際にここで必要としないmuch more stuff(イントロスペクション機能、動的プロパティ、シグナル/スロット、スレッドアフィニティ、イベント処理、国際化など)を提供します。

Qtおよびthe C++ standard libraryには、独自の所有権または共有所有権のセマンティクスによってオブジェクトのライフタイム管理を実装できるスマートポインタがあります。

データロードをグローバルスレッドプールにオフロードし、準備が整うとすぐにこれらのデータをビューに表示するモデルの例については、this answerを参照してください。モデルはQObjectを継承していることに注意してください(は信号/スロットを使用してデータの変更を通知するため、を継承します)。実際にデータを保持するデータ構造がQObjectを継承する理由はありません。 。 。

+0

私はスマートポインタについても考えていました。 Answer – Sorcerer

+0

@Sorcererに感謝します。あなたのコードに現在競合状態があります(これは私の注意を引いたものです)。 'handleResult'が呼び出される前にウィンドウが破壊されたらどうなりますか?現在 'handleResult'はあなたの' BigData'オブジェクトの所有権を主張しているので、あなたの 'BigData'オブジェクトはリークします。繰り返しますが、私の答えに記載されているようにデザインを変更する必要があります。 。 。 – Mike

関連する問題