Invoquer la fente de la méthode sans connexion?
J'ai un objet live en œuvre de la manière suivante. Il est utilisé pour exécuter les longues tâches en arrière-plan. Le thread principal invoquer les tâches par l'envoi d'un signal au public slots (c'est à dire doTask). Voici une dépouillé exemple (non testé).
class MyTask : public QObject
{
Q_OBJECT
public:
MyTask();
~MyTask();
public slots:
void doTask( int param );
private slots:
void stated();
signals:
void taskCompleted( int result );
private:
QThread m_thread;
};
MyTask::MyTask()
{
moveToThread(&m_thread);
connect( &m_thread, SIGNAL(started()), this, SLOT(started()));
m_thread.start();
}
MyTask::~MyTask()
{
//Gracefull thread termination (queued in exec loop)
if( m_thread.isRunning() )
{
m_thread.quit();
m_thread.wait();
}
}
void MyTask::started()
{
//initialize live object
}
void MyTask::doTask( int param )
{
sleep( 10 );
emit taskCompleted( param*2 );
}
Cela devrait fonctionner comme prévu en tant que doTask() est invoquée par un signal. Mais si le thread principal appels doTask() directement, il sera ensuite exécuté par le thread principal. Pour certaines tâches, je veux appliquer une exécution en direct de l'objet thread, même si la fente méthode est appelée directement.
Je pourrais ajouter du code en face de doTask() pour vérifier si le thread courant est m_thread, auquel cas, il exécute la méthode. Si non je voudrais que doTask() émet un signal 'ce' de sorte que l'invocation de la doTask() est en attente dans le m_thread exec boucle et exécuté par elle dès que possible.
Comment pourrais-je le faire ?
MODIFIER: sur la Base des propositions de réponse, voici le nouveau code. Le doTask méthode maintenant les délégués de l'exécution par le live objet thread, même si elle est appelée directement par le thread principal. Appelé par le signal fonctionne toujours comme prévu.
class MyTask : public QObject
{
Q_OBJECT
public:
explicit MyTask( QObject *parent = 0 );
~MyTask();
public slots:
void doTask( int param );
private slots:
void doTaskImpl( int param );
signals:
void taskCompleted( int result );
private:
QThread m_thread;
};
MyTask::MyTask( QObject *parent) : QObject(parent)
{
moveToThread(&m_thread);
m_thread.start();
}
MyTask::~MyTask()
{
//Gracefull thread termination (queued in exec loop)
if( m_thread.isRunning() )
{
m_thread.quit();
m_thread.wait();
}
}
void MyTask::doTask( int param )
{
QMetaObject::invokeMethod( this, "doTaskImpl", Q_ARG( int, param ) );
}
void MyTask::doTaskImpl( int param )
{
//Do the live oject's asynchronous task
sleep( 10 );
emit taskCompleted( param*2 );
}
C'est le plus simple de mise en œuvre que j'ai pu trouver à l'appui de méthode asynchrone exécutions dans un thread séparé. Les invocations du doTask() les méthodes mises en file d'attente et traitées dès que le thread est démarré. Lorsqu'il est appelé à partir de l'objet thread, il sera exécuté immédiatement (pas de file d'attente).
Noter que le démarrage (le) du signal est émis uniquement lorsque le thread est démarré. Cela signifie que doTask() la méthode d'invocation en file d'attente avant que le thread est démarré exécutera avant de le commencer() la méthode la fente est invoquée. C'est la raison je l'ai enlevé de la mise en œuvre initiale. L'initialisation de l'objet doit donc de préférence être effectuée dans le constructeur.
Une question similaire a déjà répondu dans QT + Comment appeler la fente de la coutume de code C++ qui s'exécute dans un thread.
OriginalL'auteur chmike | 2010-07-21
Vous devez vous connecter pour publier un commentaire.
Vous voulez l'appeler
QMetaObject::invokeMethod
pour ce faire. Dans votre cas, il ressemblerait à quelque chose commeEst-il possible de le faire sans l'aide de la chaîne de nom pour la méthode?
OriginalL'auteur Caleb Huitt - cjhuitt
Sur la seule amélioration que je voudrais ajouter, c'est pour gagner du temps sur la recherche de la méthode:
La signature de la méthode adoptée pour
indexOfMethod
devrait inclure des arguments et être en forme normalisée (lien) si le code correct doit êtrem_doTaskImplIndex(metaObject()->indexOfMethod(metaObject()->normalizedSignature("doTaskImpl(int)")))
OriginalL'auteur Kuba Ober
Je soupçonne qu'il ya un bug dans Matache. Si j'ai bien compris Qt internes correctement puis
moveToThread(&m_thread);
échouera si
parent
n'est pas 0.OriginalL'auteur Sergey Skoblikov
Qu'en l'enveloppant dans une classe de nice?
J'ai aussi ajouté une fente
finishPlease
, qui sera ajouté comme dernier élément dans le message todo liste, et donne des informations pour le programme principal où il a effectivement traitées tous les messages en attente avant d'être tué.OriginalL'auteur at-2500