Ich habe eine Klasse ConnectionManager
mit Methode get_wifi_ssids()
, die eine Liste von SSIDs zurückgeben muss. Das Problem ist, dass man diese SSIDs braucht, um Signale und Slots zu bekommen, aber ich kann keinen Weg finden, diese Informationen zu erhalten, ohne die Methode zu beenden.Wie eine Methode ein Signal senden und warten auf den Steckplatz vor der Rückkehr?
Hier ist die Hierarchie der Klassen von der niedrigsten bis zur höchsten Ebene.
/** Controls wireless network card by commanding a software component "connman" via DBus. */
class WifiController : QObject {
Q_OBJECT
public:
void scan();
}
/** Low level interface to network interfaces. */
class NetworkController : QObject {
Q_OBJECT
public:
void scan_for_wifi() {
wifi_controller.scan();
// When scan is finished it sends the
// NetworkTechnology::scanFinished signal.
}
// Gets info from cache. This cache is updated when a `scan()` happens.
QList<AccessPointInfo> get_available_access_points;
private:
WifiController wifi_controller;
}
/** High level interface to network interfaces. */
class ConnectionManager {
public:
QList<QString> get_wifi_ssids() {
netCtrlr.scan();
// PROBLEM HERE: How do I wait for the `scanFinished` signal here, then
// continue execution and return the SSIDs from the recently-updated
// cache?
QList<AccessPointInfo> APs { netCtrlr.get_available_access_points() };
QList<QSitrng> ssids { parseAPInfo(APs) };
return ssids;
}
private:
NetworkController netCtrlr;
}
Die Gesamtheit meiner Anwendung ist in einem einzigen Thread. "connman" wird von WifiConroller
über DBus befohlen, und es ist ein separater Prozess, so offensichtlich in einem separaten Thread. Die GUI läuft in einem separaten Prozess und meine App kommuniziert mit ihr über DBus.
Eine QEventLoop
ist eine schlechte Lösung, weil es nicht in der Produktion verwendet werden soll und eher ein Hack ist, so die Kommentare in this answer.
Müssen Sie die Liste wirklich von ** get_wifi_ssids() '** zurückgeben? warum nicht die Liste in einem Signal ausstrahlen, wenn sie stattdessen verfügbar sind? Wenn Sie sie zurückgeben wollen, müssen Sie irgendwie innerhalb der Funktion anhalten, bis die Liste verfügbar ist, indem Sie entweder eine verschachtelte Ereignisschleife starten (und davon abgeraten wird) oder durch den ganzen Thread blockieren (und das wird noch mehr entmutigt)). – Mike
Ich würde vorschlagen, ein Signal mit der Liste zu senden, wenn es verfügbar ist. Oder speichern Sie die Liste in Ihrer Klasse und geben Sie Ihrem Beobachter ein Signal, um das letzte verfügbare Ergebnis aus Ihrer Klasse zu erhalten (etwa wie ['QIODevice :: readyRead()'] (https://doc.qt.io/qt -5/qiodevice.html # readyRead) Signal funktioniert). – Mike
@Mike Hmm das ist ein guter Vorschlag. Aber wieso sagen Sie, dass das Blockieren des Threads eine schlechte Idee ist (d. H. Einen Spinlock verwenden, um zu warten, bis der Scan beendet ist)? Ich habe kein GUI-Thread (es läuft in einem separaten Prozess und meine App spricht über DBus). – DBedrenko