Problem:
In Qt möchten Sie ein Lambda oder einen Funktor in jedem Thread ausführen, der über eine Ereignisschleife verfügt, ähnlich den Dispatch-Warteschlangen von GCD Objective-C.
Lösung:
Die Lösung konzentriert sich auf die Bereitstellung eines Ereignisses, das den Funktor an ein Verbraucherobjekt bindet, das sich im gewünschten Thread befindet. Dieser Vorgang wird als Metacall-Posting bezeichnet und kann auf verschiedene Arten implementiert werden.
Qt 5.10 und höher TL;DR:
Sie können Methoden für QObjects oder QThreads aufrufen direkt:
// 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 für Funktoren:
Es werden mehrere Vorlagenfunktionen bereitgestellt, um den Funktor in ein geeignetes Ereignisobjekt einzuschließen, wodurch das Posten von Metaaufrufen bequemer wird.
// 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 für Methoden/Slots:
Für Methoden oder Slots wird ein Makro definiert, um die Metacall-Veröffentlichung zu verarbeiten.
#define POST_METHOD(obj, method) \ QObject src; \ QObject::connect(&src, &QObject::destroyed, obj, method, \ Qt::QueuedConnection);
Common Code:
Der bereitgestellte Code enthält allgemeine Hilfsfunktionen und Makros, die die Metacall-Posting-Implementierung zur Verwendung in verschiedenen abstrahieren Szenarien.
Beispiel:
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"; }); }
Zusätzlicher Hinweis:
Wenn Ihr Zielthread keine Ereignisschleife hat B. einen Arbeitsthread, benötigen Sie möglicherweise einen Mechanismus, um die Ereignisschleife innerhalb des Threads zu starten. Wenn Sie beispielsweise einen Single-Shot-Timer für die Veröffentlichung von Metaaufrufen verwenden, können Sie die Ereignisschleife mit QThread::exec().
startenDas obige ist der detaillierte Inhalt vonWie führe ich Funktoren oder Lambdas in einem bestimmten Qt-Thread aus, ähnlich wie bei GCD?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!