2017-08-10 7 views
0

GUIのメインスレッドがあります。MainWindowオブジェクトが実行されています。 のコンストラクタに新しいワーカーオブジェクトとQThreadオブジェクトが作成され、ワー​​カーがスレッドに移動しますQThreadのmoveToThreadが機能しません

MainWindow.cpp

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow) 
{ 
    std::cout<<"MAIN_ID "<< QThread::currentThreadId()<<std::endl; 
    QThread *t_pc = new QThread; 
    worker *pc_w; 
    pc_w = new pc_worker(); 
    pc_w->moveToThread(t_pc); 
    t_pc->start(); 
    pc_w->initialize(); 
    // ... 
} 

worker.cpp

:、問題は、そのIDを印刷するときに、それらが同じであるということです
worker::worker(QObject *parent) : QObject(parent) { 

} 

void worker::initialize() { 
    std::cout << "INITIALIZE " << QThread::currentThreadId() << std::endl; 
} 

私が取得:

MAIN_ID 0x7f4009ccb780 
INITIALIZE 0x7f4009ccb780 

間違っているのですか?

+0

しかし、SLOT/SIGNALを使用してワーカークラスを呼び出すと、印刷されたIDが異なります –

+2

関数を直接呼び出すと、呼び出し元のスレッドで関数が実行されます。 – thuga

+0

initialize()をスロットとして定義し、MainWindowからシグナルを出します。connect(this、SIGNAL(signal_initialize())、pc_w、SLOT(initialize())、Qt :: QueuedConnection)のように接続します。 –

答えて

0

は例えば、代わりにdiretly pc_w->initialize()を呼び出すinvokeMethodを使用してみてください。:

QMetaObject::invokeMethod(pc_w, "initialize", Qt::QueuedConnection); 

あなたinitialize()方法は、この場合にはSLOTまたはSIGNALでなければなりません。

1

回答:moveToThreadですが、期待通りのものではありません。

pc_w->moveToThread(t_pc)を呼び出した後は、pc_wのメンバー機能がすべてt_pcで呼び出されたように見えます。しかし、それはmoveToThread()のことではありません。

moveToThread()の目的は、QObject「スレッドアフィニティ」つまりオブジェクトが存在するスレッドを変更することです。 しかし、基本レベルのは、Qt::QueuedConnectionでシグナルに接続されているすべてのオブジェクトのスロットがと呼び出され、その特定のスレッドで(実行)が呼び出されるという保証に過ぎません。

メンバ関数は、引き続き呼び出すスレッドで実行されます。あなたの場合、initialize()をGUIスレッドから呼び出すので、QThread::currentThreadId()はそのスレッドのidを与えます。

スレッドイベントループでthread affinitythis articleの公式ドキュメントを読むことを本当にお勧めします。

QThread* thread = new QThread; 
Worker* worker = new Worker; 

// Uses Qt::AutoConnection (default) 
// which will be transalted into Qt::QueuedConnection 
QObject::connect(thread, &QThread::started, worker, &Worker::initialize); 

std::cout<<"MAIN_ID "<< QThread::currentThreadId()<<std::endl; 

worker->moveToThread(thread); 
thread->start(); 

出力:

MAIN_ID 0000000000003E5C 
INITIALIZE 0000000000003DAC 

が人為的に同じ効果を達するスレッドのイベントループに "コールinitialize()" イベントを置く提案triveltソリューション。ただし、コンパイル時のチェックは実行されません( "initialize"は文字列として指定されます)。

関連する問題