如何让方法在返回之前发送信号并等待插槽?

DBe*_*nko 3 c++ qt slot c++11 qt-signals

我有一个ConnectionManager方法的类get_wifi_ssids()必须返回一个SSID列表.问题是需要使用这些SSID信号和插槽,但我无法找到一种方法来检索该信息而无需先退出该方法.

这是从最低级别到最高级别使用的类的层次结构.

/** 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;
}
Run Code Online (Sandbox Code Playgroud)

我的整个应用程序都在一个线程中."connman"由WifiConrollervia DBus命令,它是一个单独的进程,所以很明显在一个单独的线程中.GUI在一个单独的进程中运行,我的应用程序通过DBus与它通信.

QEventLoop根据这个答案中的评论,A 是一个糟糕的解决方案,因为它并不意味着在生产中使用,而且更像是黑客攻击.

小智 5

由于扫描操作是异步的,因此您无法真正拥有扫描SSID并返回它们的方法,因为等待扫描完成是一种阻塞操作.阻止操作会阻止事件循环工作,并阻止信号信息进行处理.

您可以在get_wifi_ssids方法内部使用本地事件循环,但这会阻止应用程序的其余部分工作.如果WiFi扫描中有任何挂断,程序将在其中冻结.

相反,重新设计类以便在需要时开始扫描,并get_wifi_ssids返回有关接入点的最新信息.