繁体   English   中英

如何在不阻塞主线程的情况下使用Qt-Dbus绑定

[英]How to use Qt-Dbus bindings without blocking the main thread

我的目标是使用Qt的DBus绑定创建一个库。

我试图创建一个Qt应用程序而不在主线程中启动QEventLoop (由QCoreApplication类提供)。

这是一个简约的应用程序示例,使用QT-4.6.2版本正常工作但使用QT-4.8或更高版本阻止内省。

DBusHandler.hpp

#pragma once
#include <iostream>
#include <QtCore/QThread>
#include <QtCore/QtCore>
#include <QtDBus/QDBusInterface>

class DBusHandler : public QThread
{
    Q_OBJECT;

private:     
    void run(void)
    {
        QDBusConnection connection = QDBusConnection::sessionBus();

        connection.registerService("my.qdbus.example");
        connection.registerObject("/", this, QDBusConnection::ExportAllSlots);
        exec();
    }

public:
    DBusHandler(void) {}
    virtual ~DBusHandler(void) {}

    void stop(void)
    {
        QDBusConnection connection = QDBusConnection::sessionBus();

        connection.unregisterObject("/");
        connection.unregisterService("my.qdbus.example");
        connection.disconnectFromBus(connection.name());
        QThread::quit();
    }

public slots:
    void remoteCall(QByteArray message)
    {
        std::cout << "Message size: " << message.size() << std::endl;
    }
};

main.cpp中

#include "DBusHandler.hpp"

int main(int ac, char **av)
{
    QCoreApplication app(ac, av);
    DBusHandler handler;

    handler.moveToThread(&handler);

    handler.start();
    while (not handler.isRunning());

    // app.exec();
    sleep(10); // Gives time to call using the command line: "qdbus my.qdbus.example / local.DBusHandler.remoteCall a_message"

    handler.stop();
    while (handler.isRunning());
}

正如您在main.cpp文件中看到的那样, app.exec()已被注释掉,但使应用程序在QT-4.8或更高版本(5.3.0)上正常工作。

我的问题如下:在Qt-4.8或5.3上,是否可以使用Qt的DBus绑定调用另一个线程中的app.exec()

背景 :有一个名为QDBusConnectionPrivate的私有类,它继承自QObject并处理所有网络。 不幸的是,如果你看一下qdbusconnection.cpp:1116你会看到Qt硬编码moveToThreadQCoreApplication::instance()

您应该提交一个增强请求,以允许用户创建使用用户指定的线程或事件循环的QDBusConnection。 请参阅下面的更新

与此同时 ,如果你喜欢做一些危险的事情,你可以通过创建自己的QDbusConnection子类(我称之为SpecializedDBusConnection )来自行破解它,它将QThread作为你希望将QDbusConnectionPrivate实例移动到的位置的第三个参数。 然后使用该类创建连接而不是默认的QDbusConnection::sessionBus()

由于这是使用一些私有类,它需要包含一些私有头文件(在下面的代码中注明),这反过来将尝试包含各种dbus库头,这将需要修改项目的INCLUDEPATH以包含dbus库包括路径。

我已经在Qt 5.3.0和Qt 4.8.6上验证了这一点。

更新:Qt 5.6中,QtDBus被重构为使用线程进行传入/传出消息处理; 不再阻塞主线程!

DBusHandler.hpp

#pragma once
#include <iostream>
#include <QtCore/QThread>
#include <QtCore/QtCore>
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusConnectionInterface>

#include "/path/to/Qt5.3.0/5.3/Src/qtbase/src/dbus/qdbusconnection_p.h"

class SpecializedDBusConnection : public QDBusConnection {
    const char *ownName;
public:
    inline SpecializedDBusConnection(BusType type, const char *name, QThread *thread)
        : QDBusConnection(connectToBus(type, QString::fromLatin1(name))), ownName(name)
    {
        if (QDBusConnectionPrivate::d(*this)) {
            QDBusConnectionPrivate::d(*this)->moveToThread(thread);
        }
    }

    inline ~SpecializedDBusConnection()
    { disconnectFromBus(QString::fromLatin1(ownName)); }
};

class DBusHandler : public QThread
{
    Q_OBJECT;

private:     
    void run(void)
    {
        QDBusConnection connection = SpecializedDBusConnection(QDBusConnection::SessionBus, "qt_default_session_bus", this);

        connection.registerService("my.qdbus.example");
        connection.registerObject("/", this, QDBusConnection::ExportAllSlots);

        exec();
    }
[snip]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM