使用基于QDbusAbstractInterface(通过qdbusxml2cpp)构build的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代码为我们做了这个 – 然后当我们得到信号改变状态,并且如果需要的话,连接或断开对象的信号。
所有我发现的例子要么忽略这个问题,要么就是退出,如果服务器对象不存在,不要处理它消失。 Car / Controller Qt示例至less会注意到服务器是否消失,如果isValid()在使用期间变为false,而是轮询isValid(),则会打印“Disconnected”。
添加:
请注意,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
,它允许监视一个特定的服务,而不是所有的。