Heim >Backend-Entwicklung >C++ >Wie führe ich Funktoren oder Lambdas in einem bestimmten Qt-Thread aus, ähnlich wie bei GCD?

Wie führe ich Funktoren oder Lambdas in einem bestimmten Qt-Thread aus, ähnlich wie bei GCD?

DDD
DDDOriginal
2024-12-16 18:35:12133Durchsuche

How to Execute Functors or Lambdas in a Specific Qt Thread, Similar to GCD?

Wie führe ich einen Funktor oder ein Lambda in einem gegebenen Thread in Qt, GCD-Stil aus?

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().

starten

Das 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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn