Ich habe zwei Objekte, die in verschiedenen Threads lebt und ich versuche herauszufinden, ob ein verwendetes Muster Thread-sicher ist oder nicht.Thread-Sicherheit des Aufrufs von QObject-Methode von einem anderen (nicht-qt) Thread?
Das erste Objekt ist QObject-abgeleitet und lebt (wurde in erstellt) der Haupt-Qt-Thread. Die Klasse enthält einige Q_INVOKABLE
Methoden, die von QML aufgerufen werden sollten, einige signal*()
Methoden definiert als signals:
und einige Emit*()
(normale) Methoden, die ich als Wrapper zum Emittieren von Signalen verwenden. Zum Beispiel:
void MyQObjectClass::EmitStatus(void) {
emit signalStatusChange(_status);
}
Normalerweise höre ich für diese Signale in QML. Das zweite Objekt ist nicht QObject-abgeleitet und lebt in einem zweiten Thread (pthread
). Dieser Thread führt seine eigene Ereignisschleife (libev) aus und löst Ereignisse aus. Ich kann nichts in Verbindung mit Qt in diesem Thread verwenden, da ich die benutzerdefinierte libev
Ereignisschleife brauche. Für dieses Objekt habe ich einige Notify*()
Methoden definiert, die asynchrone Ereignisse über libev
senden, um von Rückrufen abgeholt zu werden.
Ich muss in der Lage sein, zwischen den zwei Objekten/Threads zu kommunizieren, aber ich bin nicht sicher, wie man das sicher macht.
Das eigentliche Design ist es, das pthread
Thread-Objekt rufen Sie die verschiedenen Emit*()
Methoden direkt, so dass das QObject die Informationen ordnungsgemäß an Qt/QML propagieren kann. Wenn ich Informationen von Qt/QML an das pthread
/libev
Objekt senden muss, rufe ich (vom Qt-Thread) die Methoden Notify*()
.
Wenn Accessing QObject Subclasses from Other Threads lesen, heißt es:
QObject und alle ihre Unterklassen sind nicht Thread-sicher. Dies umfasst das gesamte Ereignisliefersystem.
aber dann weiter heißt es, dass:
Auf der anderen Seite, können Sie sicher Signale von Ihrem QThread :: run() Implementierung emittieren können, da das Signal Emission Thread-sicher ist.
Also meine Frage ist, ist das oben beschriebene Design thread-sicher? Kann ich sicher anrufen myQObject->EmitMySignal()
, die wiederum emit signalMySignal()
aufrufen, alles aus dem pthread
Objekt?
Ich denke, Sie sollten dies mit 'postEvent' umgehen, anstatt direkt auf das' QObject' zuzugreifen. 'postEvent' ist threadsicher und wurde für diesen Zweck entwickelt, wenn Sie keine normale Signal/Slot-Verbindung verwenden wollen oder können. – Resurrection
Emitting-Signal ist Thread-Safe, wie angegeben. Das Lesen des Werts der Elementvariablen ist jedoch nicht Thread-sicher. Sie müssen also den Zugriff auf '_status 'schützen, wenn auf mehrere Threads zugegriffen wird. Das Aufrufen einer * QObject * -Methode aus mehreren Threads ist fehleranfällig. Wenn Sie das tun, empfehle ich ein paar Dinge: 1. Teilen Sie die Methoden in "von anderen Threads" und "normale" Methoden und haben Sie eine eindeutige Namenskonvention * diese. 2. Unterteilen Sie die Member-Variablen auf die gleiche Weise und stellen Sie sicher, dass der Zugriff auf Member-Variablen, die aus mehreren Threads verwendet werden sollen, mutex-geschützt ist. 3. Überprüfen Sie den Code! – hyde