Как испустить сигнал кросс-нитки в Qt?

Документация Qt гласит, что сигналы и слоты могут быть direct , queued и auto .

Он также заявил, что если объект, которому принадлежит слот «жизни» в streamе, отличном от объекта, которому принадлежит сигнал, излучает такой сигнал, будет как сообщение отправки – сигнал emit будет возвращаться мгновенно, и метод slot будет вызван в цикле событий целевого streamа.

К сожалению, в документации не указано, что означает «жизнь», и нет примеров. Я пробовал следующий код:

main.h:

 class CThread1 : public QThread { Q_OBJECT public: void run( void ) { msleep( 200 ); std::cout << "thread 1 started" << std::endl; MySignal(); exec(); } signals: void MySignal( void ); }; class CThread2 : public QThread { Q_OBJECT public: void run( void ) { std::cout << "thread 2 started" << std::endl; exec(); } public slots: void MySlot( void ) { std::cout << "slot called" << std::endl; } }; 

main.cpp:

 int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); CThread1 oThread1; CThread2 oThread2; QObject::connect( & oThread1, SIGNAL( MySignal() ), & oThread2, SLOT( MySlot() ) ); oThread1.start(); oThread2.start(); oThread1.wait(); oThread2.wait(); return a.exec(); } 

Выход:

 thread 2 started thread 1 started 

MySlot() никогда не называется 🙁 Что я делаю неправильно?

    С вашим кодом довольно много проблем:

    • как сказал Эван, ключевое слово emit отсутствует
    • все ваши объекты живут в основном streamе, только код в методах запуска живет в других streamах, что означает, что слот MySlot будет вызываться в основном streamе, и я не уверен, что это то, что вы хотите
    • ваш слот никогда не будет вызываться, так как основной цикл событий никогда не запускался: ваши два вызова wait () будут только таймаутом после очень долгого времени (и вы, вероятно, убьете свое приложение до того, как это произойдет), и я не думаю это то, что вы хотите, так или иначе, они действительно бесполезны в вашем коде.

    Этот код, скорее всего, будет работать (хотя я его не тестировал), и я думаю, что он делает то, что вы хотите:

     class MyObject : public QObject { Q_OBJECT public slots: void MySlot( void ) { std::cout << "slot called" << std::endl; } }; class CThread1 : public QThread { Q_OBJECT public: void run( void ) { std::cout << "thread 1 started" << std::endl; int i = 0; while(1) { msleep( 200 ); i++; if(i==1000) emit MySignal(); } } signals: void MySignal( void ); }; class CThread2 : public QThread { Q_OBJECT public: void run( void ) { std::cout << "thread 2 started" << std::endl; exec(); } }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); CThread1 oThread1; CThread2 oThread2; MyObject myObject; QObject::connect( & oThread1, SIGNAL( MySignal() ), & myObject, SLOT( MySlot() ) ); oThread2.start(); myObject.moveToThread(&oThread2) oThread1.start(); return a.exec(); } в class MyObject : public QObject { Q_OBJECT public slots: void MySlot( void ) { std::cout << "slot called" << std::endl; } }; class CThread1 : public QThread { Q_OBJECT public: void run( void ) { std::cout << "thread 1 started" << std::endl; int i = 0; while(1) { msleep( 200 ); i++; if(i==1000) emit MySignal(); } } signals: void MySignal( void ); }; class CThread2 : public QThread { Q_OBJECT public: void run( void ) { std::cout << "thread 2 started" << std::endl; exec(); } }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); CThread1 oThread1; CThread2 oThread2; MyObject myObject; QObject::connect( & oThread1, SIGNAL( MySignal() ), & myObject, SLOT( MySlot() ) ); oThread2.start(); myObject.moveToThread(&oThread2) oThread1.start(); return a.exec(); } 

    Теперь MyObject будет жить в thread2 (благодаря moveToThread).

    MySignal должен быть отправлен из thread1 (думаю, что я не уверен в этом, его можно отправить из основного streamа, это не имеет значения).

    В streamе 1 не требуется цикл событий, поскольку для испускания сигнала не требуется цикл событий. Цикл событий необходим в streamе 2 (с помощью exec ()) для приема сигнала.

    MySlot вызывается в thread2.

    Не подclassы QThread для Qt 4.4+

    Хотя ответ Аиуа хорош, я хочу указать на некоторые проблемы с QThread и Qt 4.6 или 4.7.

    Эта статья подводит итог: http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

    Отсутствие документации по части Qt

    К сожалению, проблема связана с отсутствием обновлений документации. До Qt 4.4 QThread не выполнял реализацию по умолчанию (), что означало, что вам пришлось подclassифицировать QThread, чтобы использовать его.

    Если вы используете Qt 4.6 или 4.7, вы почти наверняка не должны подclassифицировать QThread.

    Использовать moveToThread

    Ключ к созданию слотов для выполнения в рабочем streamе заключается в использовании метода moveToThread, как указывал Aiua.

    Давайте будем гением компьютера.