2009-09-14 29 views
11

Với proxy Qt DBus được xây dựng trên QDbusAbstractInterface (qua qdbusxml2cpp), cách nào tốt nhất để xử lý dịch vụ/đối tượng bạn muốn giao tiếp không khả dụng khi bạn khởi động? Lưu ý: Tôi không quan tâm chỉ đơn giản là biết nó (bạn có thể sử dụng BlahService.isValid() để tìm ra điều đó); Tôi muốn để có thể biết nếu nó hợp lệ, và biết khi nào nó trở nên hợp lệ để tôi có thể thay đổi trạng thái (và phát sóng thay đổi trạng thái đó bằng tín hiệu), và thay đổi trạng thái đó thực hiện các công cụ khác. Ngược lại, tôi muốn biết khi nào nó không còn hợp lệ vì những lý do tương tự.Đang chờ dịch vụ DBus khả dụng trong Qt

Nếu không theo dõi trạng thái của dịch vụ:

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

Có lẽ chúng ta cần phải xem cho NameOwnerChanged trên đối tượng kết nối dbus - trừ khi mã dbus QT của hiện điều này cho chúng ta - và sau đó khi chúng tôi nhận được rằng tình trạng thay đổi tín hiệu và nếu cần kết nối hoặc ngắt kết nối tín hiệu khỏi đối tượng.

Tất cả các ví dụ tôi thấy hoặc bỏ qua sự cố hoặc chỉ cần thoát nếu đối tượng máy chủ không tồn tại và không xử lý nó. Ví dụ về Ô tô/Bộ điều khiển Qt ít nhất là thông báo nếu máy chủ biến mất và in "Đã ngắt kết nối" nếu isValid() trở thành sai trong khi sử dụng, nhưng nó bỏ phiếu làValid().

Added:

Lưu ý rằng QtDbusAbtractInterface đăng ký thay đổi quyền sở hữu của máy chủ (NameOwnerChanged), và cập nhật isValid() khi thay đổi xảy ra. Vì vậy, tôi nghi ngờ bạn có thể kết nối với tín hiệu serverOwnerChanged đó trực tiếp để tìm hiểu về thay đổi quyền sở hữu và sử dụng làm chỉ báo để thử lại - mặc dù bạn sẽ không thể tin cậy isValid vì nó có thể được cập nhật trước hoặc sau khi bạn nhận được tín hiệu.

Ngoài ra (xấu xí) bạn có thể thiết lập bộ đếm thời gian và thăm dò ý kiến ​​cho isValid().

Trả lời

9

Ok, vì không có ai trả lời, tôi đã tìm thấy câu trả lời trong khi chờ đợi:

Bạn muốn xem 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(); 
     } 
    } 
} 

Lưu ý rằng có may là điều kiện chủng tộc với phương pháp thực hiện trên FooService từ bên trong serviceOwnerChanged - Tôi không chắc chắn nếu chúng là một tác dụng phụ của sự ràng buộc (dbus-C++ trong trường hợp thử nghiệm của tôi), hoặc vốn có trong thiết kế của dbus (có thể - không có trên danh sách gửi thư dbus sẽ trả lời câu hỏi). Nếu có điều kiện chạy thực, bạn có thể đợi tín hiệu Sẵn sàng()/bất kỳ điều gì, nếu bạn kiểm soát API DBus. Nếu bạn không kiểm soát đầu kia, bạn có thể thêm độ trễ rất ngắn hoặc bạn cũng có thể xem AddMatch() để đảm bảo chủ sở hữu mới cũng đã thêm một kết quả trùng khớp vào tên.

+0

Tôi sử dụng dòng này để chỉ nhận tín hiệu cho dịch vụ tôi muốn: 'QDBusConnection :: systemBus(). Connect (" org.freedesktop.DBus ","/org/freedesktop/DBus "," org.freedesktop. DBus ", " NameOwnerChanged ", QStringList() <<" org.freedesktop.Avahi "," sss ", điều này, SLOT (AvahiNameOwnerChanged (QString, QString, QString)));' Đối với điều kiện chủng tộc, tôi xóa giao diện cũ của tôi và nhận một giao diện mới khi tôi nhận được tín hiệu này. – Harvey

3

Với Qt 5.3, serviceOwnerChanged không còn được dùng nữa. Sử dụng QDBusServiceWatcher cho phép xem một dịch vụ cụ thể thay vì tất cả.

Các vấn đề liên quan