Appeler une fonction dans le thread enfant dans Qt?
Question
J'ai un thread principal qui appelle une fonction de thread enfant à différents moments, mais je ne suis pas sûr que ce soit la bonne façon de le faire dans Qt.What est faux avec le code ci-dessous et à la recherche d'une meilleure alternative
Un thread principal fonctionne à l'infini quand un thread principal libère le verrou que l'enfant effectue un travail.
#include <QtCore/QCoreApplication>
#include <QSemaphore>
#include <QThread>
QSemaphore sem(0);
class Background : public QThread
{
protected:
void run()
{
for(;;)
{
sem.acquire(1);
qDebug("Child function ran");
}
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Background child;
child.start();
qDebug("Main running");
qDebug("release a lock");
sem.release(1);
qDebug("Do somework in main");
//call child
sem.release(1);
sem.release(1);
return a.exec();
}
La solution
Modifier: retravailler l'intégralité du message afin de couvrir également les bases.
Background.h
:
#ifndef BACKGROUND_H
#define BACKGROUND_H
#include <QThread>
#include <QObject>
class Background : public QThread
{
Q_OBJECT
public:
Background(QObject* parent = 0):QThread(parent){}
protected:
void run()
{
qDebug(qPrintable(QString("Child function ran in thread: %1").arg(QThread::currentThreadId())));
}
};
class BackgroundConcurrent : public QObject
{
Q_OBJECT
public:
BackgroundConcurrent(QObject* parent = 0):QObject(parent){}
public slots:
void doWork() const
{
qDebug(qPrintable(QString("Concurrent child function ran in thread: %1").arg(QThread::currentThreadId())));
}
};
class BackgroundTrigger : public QObject
{
Q_OBJECT
public:
BackgroundTrigger(QObject* parent = 0):QObject(parent){}
~BackgroundTrigger()
{
foreach(QObject* child, children())
{
QThread* childThread = qobject_cast<QThread*>(child);
if (childThread)
childThread->wait();
}
}
public slots:
void triggerWorker()
{
Background* child = new Background(this);
child->start();
}
};
#endif // BACKGROUND_H
main.cpp
:
#include "Background.h"
#include <QCoreApplication>
#include <QtConcurrentRun>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// Using QThread
BackgroundTrigger childTrigger;
qDebug(qPrintable(QString("Main function ran in thread: %1").arg(QThread::currentThreadId())));
// Call child
childTrigger.triggerWorker();
childTrigger.triggerWorker();
// Using QtConcurrent
BackgroundConcurrent cchild;
QFuture<void> future1 = QtConcurrent::run(&cchild, &BackgroundConcurrent::doWork);
QFuture<void> future2 = QtConcurrent::run(&cchild, &BackgroundConcurrent::doWork);
return 0;
}
Exemple de sortie:
Main function ran in thread: 1087038064 Child function ran in thread: 1091267472 Child function ran in thread: 1093417872 Concurrent child function ran in thread: 1095519120 Concurrent child function ran in thread: 1097644944
Assurez-vous d'exécuter moc sur vos fichiers d'en-tête, qmake et < a href = "http://www.cmake.org/cmake/help/documentation.html" rel = "nofollow noreferrer"> cmake prend en charge la création de vos fichiers makefiles.
Voici le fichier CMakeLists.txt
que j'ai utilisé pour construire le code:
cmake_minimum_required(VERSION 2.6)
#Project name
project(TEST)
#Use Qt4
find_package(Qt4)
if(QT4_FOUND)
set(QT_USE_QTOPENGL TRUE)
include(${QT_USE_FILE})
set(LIBS
${QT_LIBRARIES}
)
#Source files (*.cpp, *.o)
set(TEST_SRCS main.cpp)
#Header files (*.h[pp])
set(TEST_HDRS Background.h)
#Qt macros to handle uic, moc, etc...
QT4_WRAP_CPP(TEST_MOC ${TEST_HDRS} OPTIONS -nw)
set(TEST_ALLSRC ${TEST_SRCS} ${TEST_MOC})
#Create main
add_executable(test ${TEST_ALLSRC})
target_link_libraries(test ${LIBS})
endif(QT4_FOUND)
Autres conseils
En fait, votre solution actuelle au problème est un très bon bidouillage.
Si vous préférez le faire dans un "nettoyeur" " mode, vous devriez commencer une boucle d’événements dans votre thread de travail. Ensuite, le thread de travail sera capable de recevoir des signaux du thread principal. Vous pouvez appeler une fonction du thread enfant (à l'aide du mécanisme signal / slot) à partir du thread principal pour déclencher l'opération.
Voir ici pour plus de détails: http://doc.trolltech.com/4.2/threads. html # par-thread-event-loop
(Conseil: L'idée principale est de créer l'objet de réception dans le thread de travail; ses emplacements seront alors traités dans ce thread; vous pouvez également utiliser la fonction MoveToThread ())
Il semble que vous souhaitiez utiliser un signal pour cela, afin de s’adapter au style Qt normal. Consultez cette question ; la réponse acceptée semble également correspondre à votre question.