使用基于QDbusAbstractInterface(通过qdbusxml2cpp)构建的Qt DBus代理,处理启动时无法使用的服务/对象的最佳方法是什么?注意:我对简单地知道它不感兴趣(你可以使用BlahService.isValid()来找出它);我希望能够知道它是否有效,并知道它何时变为有效所以我可以改变状态(并用信号广播状态变化),并在该状态变化做其他事情。相反,我想知道它出于类似的原因何时不再有效。

不跟踪服务状态:

#define CONNECT_DBUS_SIG(x,y) connect(blah,SIGNAL(x),this,SLOT(y))

// FIX - should watch for service, and also handle it going away and
// coming back
blah = new BlahService("com.xyzzy.BlahService", "/com/xyzzy/BlahService",
                           QDBusConnection::sessionBus(), this);
if (!blah)
    return 0;
if (blah.isValid())
{
    CONNECT_DBUS_SIG(foo(),Event_foo());
}
else
{
    // Since we aren't watching for registration, what can we do but exit?
}

可能我们需要在DBus连接对象上注意NameOwnerChanged - 除非QT的dbus代码为我们做这个 - 然后当我们得到那个信号改变状态时,如果需要连接或断开来自对象的信号。

我找到的所有示例要么忽略该问题,要么只是在服务器对象不存在时退出,并且不处理它会消失。汽车/控制器Qt示例至少注意到服务器是否消失并打印“已断开连接”。如果isValid()在使用过程中变为false,但它是polle isValid()。

添加了:

请注意,QtDbusAbtractInterface会注册服务器所有权的更改(NameOwnerChanged),并在发生更改时更新isValid()。因此,我怀疑您可以直接连接到该serverOwnerChanged信号,以了解所有权的更改并将其用作指示器再次尝试 - 尽管您无法信任isValid,因为它可能会在您发出信号之前或之后更新。

或者(丑陋)你可以设置一个计时器并轮询isValid()。

有帮助吗?

解决方案

好的,既然没有人回答,我在此期间找到了答案:

您想要观看NameOwnerChanged:

// subscribe to notifications about when a service is registered/unregistered
   connect(QDBusConnection::sessionBus().interface(),
           SIGNAL(serviceOwnerChanged(QString,QString,QString)),
           this,SLOT(serviceOwnerChanged(QString,QString,QString)));

void 
VcsApplicationController::serviceOwnerChanged(const QString &name,
                                              const QString &oldOwner,
                                              const QString &newOwner)
{
    Q_UNUSED(oldOwner);
    if (name == "com.foo.bar.FooService")
    {
        qLog(Whatever) << "serviceOwnerChanged" << name << oldOwner << newOwner;
        if (!newOwner.isEmpty())
        {
            // New owner in town
            emit Initialized();
            // or if you control the interface and both sides, you can wait for
            // a "Ready()" signal before declaring FooService ready for business.
        }
        else
        {
            // indicate we've lost connection, etc
            emit Uninitialized();
        }
    }
}

请注意,可能是在serviceOwnerChanged中对FooService执行方法的竞争条件 - 我不确定它们是否是绑定的副作用(dbus-c ++在我的测试中)案例),或dbus设计中固有的(可能 - 在dbus邮件列表上没有打开将回答问题)。如果 是真正的竞争条件,您可以等待Ready()/无论什么信号,如果您控制DBus API。如果您不控制另一端,您可以添加非常短的延迟,或者您也可以观看AddMatch()以确保新所有者也在名称上添加了匹配项。

其他提示

使用Qt 5.3,不推荐使用 serviceOwnerChanged 。使用 QDBusServiceWatcher ,可以观看具体服务而不是全部。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top