2016-06-29 8 views
1

Я написал простую слот слота с использованием Qt. Я хочу отправить сигнал в другой поток, который заканчивается из основного потока.Как сигнализировать слот в другом потоке в Qt

Вот мой код:

class Thread1 : public QThread 
{ 
    Q_OBJECT 


    void run() 
    { 
     exec(); 
    } 
public: 
    Thread1(QObject* parent); 

public slots: 
    void a() 
    { 
     qInfo()<<QThread::currentThreadId(); 
    } 
}; 
class Object : public QObject 
{ 
    Q_OBJECT 
public: 
    Object(){} 
    void start() 
    { 
     qInfo()<<QThread::currentThreadId(); 
     Thread1* thread = new Thread1(this); 
     connect(this,SIGNAL(a()),thread,SLOT(a())); 
     thread->start(); 
     emit a(); 
    } 

signals: 
    void a(); 
}; 

Но он возвращает:

0x7f9851c988c0 
0x7f9851c988c0 

Как я могу вызвать сигнал, который выводит другой ThreadId?

ответ

5

Вы получили его назад. A QThread - это ручка потока, а не сама нить. Если вы хотите запускать что-то в другом потоке, оно принадлежит равному QObject, что вы переходите к потоку. Вам вообще не нужно выводить из QThread! Вы также не должны перемещать базу QThreadQObject в самую нить. То, что вы делаете, имеет ручку для потока, живущего в самой нити. Как только резьба заканчивается, ручка становится нефункциональной (a QObject с нулем thread()).

Прежде всего, если вам нужно всего лишь запустить код, который выполняется до завершения (например, выполняет расчет) в рабочем потоке, используйте пул потоков и QtConcurrent. Он управляет все нити для вас:

#include <QtConcurrent> 
... 
QThread::currentThread()->setObjectName("main"); 
qDebug() << QThread::currentThread(); 
QtConcurrent::run([]{ qDebug() << QThread::currentThread(); } 

Если вы настаиваете на контроле жизни потока себя, вы могли бы сделать следующее:

#include <QtCore> 
struct Worker : QObject { 
    Q_SLOT void aSlot() { 
    qDebug() << QThread::currentThread(); 
    QThread::currentThread()->quit(); 
    } 
    Q_SIGNAL void aSignal(); 
    Q_OBJECT 
}; 

int main(int argc, char ** argv) { 
    QCoreApplication app{argc, argv}; 
    QThread::currentThread()->setObjectName("main"); 
    QThread thread; 
    thread.setObjectName("thread"); 
    Worker a, b; 
    b.moveToThread(&thread); 
    thread.start(); 
    QObject::connect(&a, &Worker::aSignal, &b, &Worker::aSlot); 
    emit a.aSignal(); // the signal is emitted from the main thread 
    thread.wait(); 
} 

Наконец, отметим, что QDebug класс знает, как вывести адрес объекта, класс и имя (если установлено) при передаче указателя на QObject. Таким образом, вам не нужно использовать QThread::currentThreadId(), достаточно QThread::currentThread() - и вы можете дать нить mnemonic имена, так как они QObject s, в конце концов.

+0

Что делать, если у меня есть «Worker c;», который перемещается в третий поток и также связан с 'aSignal'. Затем излучение сигнала будет запускать метод aSlot как у рабочих b, так и c, каждый в своем потоке. Правильно? – lanoxx

+0

@lanoxx Правильно. –

-2

Реализовать Thread1 конструктор как следующие:

Thread1(QObject* parent) { moveToThread(this); } 
+0

Да, это сделало работу. но для его удаления требуется родительский элемент. –

+0

Почему родитель должен быть удален? –

+0

Он напечатал, что moveToThread не может быть вызван для объекта с родительским. –

 Смежные вопросы

  • Нет связанных вопросов^_^