Impossible d’émettre les signaux de QThread

QT 5.1.0rc2, msvc 2010, Microsoft Visual Studio 2010

Il travaille le code sur Qt 4.8.4, msvc 2008

J’ai une erreur de compilation à

#if defined( HANDLE_PROCESSING_IN_MAIN_THREAD ) if(QThread::currentThread() != this) emit started(); #endif inherited::run(); 

et

 #if defined( HANDLE_PROCESSING_IN_MAIN_THREAD ) if(QThread::currentThread() != this) emit finished(); #endif 

erreur C2660: ‘QThread :: started’: la fonction ne prend pas 0 argument
erreur C2660: ‘QThread :: finish’: la fonction ne prend pas 0 argument

Dans QThread j’ai vu

 Q_SIGNALS: void started( #if !defined(Q_QDOC) QPrivateSignal #endif ); void finished( #if !defined(Q_QDOC) QPrivateSignal #endif ); 

quand j’ai défini Q_QDOC, j’ai eu beaucoup d’erreurs dans les sources QT.

QPrivateSignal est une structure vide définie dans la macro Q_OBJECT

Besoin d’une solution qui n’affecte pas l’architecture de l’application, car compatible avec Qt4.8.4

Quelques idées?

    Les signaux du fil sont émis automatiquement. Vous ne devriez jamais les émettre manuellement.

    Vous essayez d’utiliser le préprocesseur pour gérer deux variantes du code: le traitement dans le thread gui ou un thread dédié. Qt fournit un moyen très simple d’y faire face.

    1. Implémentez votre fonctionnalité de traitement dans un emplacement d’une classe dérivée de QObject . Vous pouvez également le faire dans la méthode event() réimplémentée s’il est plus facile de commencer le traitement en publiant un événement plutôt qu’en invoquant un emplacement.

    2. Si vous souhaitez que les emplacements de votre object moveToThread() exécutés dans un autre thread, utilisez la méthode moveToThread() .

    3. Vous n’avez pas besoin de dériver de QThread . Son implémentation par défaut de run() tourner une boucle d’événement locale.

    4. Si vous voulez que votre object soit compatible avec la vie dans le fil de l’interface graphique, il doit effectuer son traitement par petits morceaux et abandonner le contrôle afin que l’interface graphique ne soit pas bloquée.

    Vous trouverez ci-dessous un exemple complet qui montre comment démarrer un object de travail dans une interface graphique ou dans un thread séparé, et comment le déplacer en toute sécurité entre des threads.

     // https://github.com/KubaO/stackoverflown/tree/master/questions/qobject-thread-18653347 #include  #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) #include  #endif /// See http://stackoverflow.com/a/40382821/1329652 bool isSafe(QObject * obj) { Q_ASSERT(obj->thread() || qApp && qApp->thread() == QThread::currentThread()); auto thread = obj->thread() ? obj->thread() : qApp->thread(); return thread == QThread::currentThread(); } class Helper : private QThread { public: using QThread::usleep; }; class Worker : public QObject { Q_OBJECT int m_counter; QBasicTimer m_timer; void timerEvent(QTimerEvent * ev) override; public: Worker(QObject *parent = nullptr) : QObject(parent) {} /// This method is thread-safe. Q_SLOT void start() { if (!isSafe(this)) return (void)QMetaObject::invokeMethod(this, "start"); if (m_timer.isActive()) return; m_counter = 0; m_timer.start(0, this); } /// This method is thread-safe. Q_INVOKABLE void startInThread(QObject *targetThread) { if (!isSafe(this)) return (void)QMetaObject::invokeMethod(this, "startInThread", Q_ARG(QObject*, targetThread)); QObject::moveToThread(qobject_cast(targetThread)); start(); } Q_SIGNAL void done(); Q_SIGNAL void progress(int percent, bool inGuiThread); }; void Worker::timerEvent(QTimerEvent * ev) { const int busyTime = 50; // [ms] - longest amount of time to stay busy const int testFactor = 128; // number of iterations between time tests const int maxCounter = 30000; if (ev->timerId() != m_timer.timerId()) return; const auto inGuiThread = []{ return QThread::currentThread() == qApp->thread(); }; QElapsedTimer t; t.start(); while (1) { // do some "work" Helper::usleep(100); m_counter ++; // exit when the work is done if (m_counter > maxCounter) { emit progress(100, inGuiThread()); emit done(); m_timer.stop(); break; } // exit when we're done with a timed "chunk" of work // Note: QElapsedTimer::elapsed() may be expensive, so we call it once every testFactor iterations if ((m_counter % testFactor) == 0 && t.elapsed() > busyTime) { emit progress(m_counter*100/maxCounter, inGuiThread()); break; } } } class Window : public QWidget { Q_OBJECT QVBoxLayout m_layout{this}; QPushButton m_startGUI{"Start in GUI Thread"}; QPushButton m_startWorker{"Start in Worker Thread"}; QLabel m_label; QThread m_thread{this}; Worker m_worker; Q_SLOT void showProgress(int p, bool inGuiThread) { m_label.setText(QSsortingng("%1 % in %2 thread") .arg(p).arg(inGuiThread ? "gui" : "worker")); } Q_SLOT void on_startGUI_clicked() { m_worker.startInThread(qApp->thread()); } Q_SLOT void on_startWorker_clicked() { m_worker.startInThread(&m_thread); } public: Window(QWidget *parent = {}, Qt::WindowFlags f = {}) : QWidget(parent, f) { m_layout.addWidget(&m_startGUI); m_layout.addWidget(&m_startWorker); m_layout.addWidget(&m_label); m_thread.start(); connect(&m_worker, SIGNAL(progress(int,bool)), SLOT(showProgress(int,bool))); connect(&m_startGUI, SIGNAL(clicked(bool)), SLOT(on_startGUI_clicked())); connect(&m_startWorker, SIGNAL(clicked(bool)), SLOT(on_startWorker_clicked())); } ~Window() { m_thread.quit(); m_thread.wait(); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); Window w; w.show(); return a.exec(); } #include "main.moc"