等待一个DBus服务在Qt中可用

问题描述:

使用基于QDbusAbstractInterface(通过qdbusxml2cpp)构建的Qt DBus代理,处理想要连接的服务/对象在启动时不可用的最佳方式是什么?注意:我对感兴趣的并不感兴趣(可以使用BlahService.isValid()来查找);我希望能够知道它是否有效,并知道它什么时候变得有效,以便我可以改变状态(并用信号广播状态改变),并且在状态改变时做其他事情。相反,我想知道由于类似原因它何时不再有效。等待一个DBus服务在Qt中可用

没有跟踪服务的状态:

#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? 
} 

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

我发现的所有例子都会忽略这个问题,或者只是在服务器对象不存在的情况下退出,并且不会处理它。 Car/Controller Qt示例至少会注意到服务器是否消失并在使用过程中isValid()变为false时打印“Disconnected”,但它是轮询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邮件列表上不会回答这个问题)。如果是一个真实的竞争条件,那么如果您控制DBus API,则可以等待Ready()/任何信号。如果你不控制另一端,你可以添加一个非常短暂的延迟,或者你也可以看AddMatch()以确保新的所有者也添加了名称上的匹配。

+0

我使用这一行来获取我想要的服务的信号:'QDBusConnection :: systemBus()。connect(“org.freedesktop.DBus”,“/ org/freedesktop/DBus”,“org.freedesktop。 DBus“, ”NameOwnerChanged“, QStringList() Harvey 2012-04-16 00:20:12

对于Qt 5.3,不建议使用serviceOwnerChanged。使用QDBusServiceWatcher,它允许观看特定的服务而不是全部。