Problème :
Dans Qt, vous souhaitez exécuter un lambda ou un foncteur dans n'importe quel thread doté d'une boucle d'événement, similaire à la répartition de GCD files d'attente en Objective-C.
Solution :
La solution se concentre sur la fourniture d'un événement qui enveloppe le foncteur vers un objet consommateur résidant dans le thread souhaité. Cette opération est appelée publication de métaappels, et elle peut être implémentée de plusieurs manières.
Qt 5.10 & Up TL;DR :
Vous pouvez appeler des méthodes sur QObjects ou QThreads directement :
// Invoke on the main thread QMetaObject::invokeMethod(qApp, []{ ... }); // Invoke on an object's thread QMetaObject::invokeMethod(obj, []{ ... }); // Invoke on a particular thread QMetaObject::invokeMethod( QAbstractEventDispatcher::instance(thread), []{ ... });
TL;DR pour les foncteurs :
Plusieurs fonctions de modèle sont fournies pour envelopper le foncteur dans un objet d'événement approprié, ce qui rend la publication de méta-appels pratique.
// Post to the main thread sync void execInMainThread_sync(std::function<void(void)> func) { if(qApp->thread() == QThread::currentThread()) func(); else { ((App*) qApp)->invokeGenericExec(func, Qt::BlockingQueuedConnection); } } // Post to the main thread async void execInMainThread_async(std::function<void(void)> func) { ((App*) qApp)->invokeGenericExec(func, Qt::QueuedConnection); }
TL;DR pour Méthodes/Slots :
Pour les méthodes ou les slots, une macro est définie pour gérer la publication du métacall.
#define POST_METHOD(obj, method) \ QObject src; \ QObject::connect(&src, &QObject::destroyed, obj, method, \ Qt::QueuedConnection);
Code commun :
Le code fourni comprend des fonctions d'assistance et des macros courantes qui résument l'implémentation de la publication des métaappels pour une utilisation dans différents scénarios.
Exemple :
void test1() { QThread t; QObject o; o.moveToThread(&t); // Execute in given object's thread postToObject([&]{ o.setObjectName("hello"); }, &o); // or postToObject(std::bind(&QObject::setObjectName, &o, "hello"), &o); // Execute in given thread postToThread([]{ qDebug() << "hello from worker thread"; }); // Execute in the main thread postToThread([]{ qDebug() << "hello from main thread"; }); }
Remarque supplémentaire :
Si votre fil de discussion cible n'a pas de boucle d'événement , tel qu'un thread de travail, vous aurez peut-être besoin d'un mécanisme pour démarrer la boucle d'événements au sein du thread. Par exemple, si vous utilisez un minuteur à prise unique pour la publication d'un méta-appel, vous pouvez démarrer la boucle d'événements à l'aide de QThread::exec().
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!