سؤال

باستخدام وكيل Qt DBus المبني على QDbusAbstractInterface (عبر qdbusxml2cpp)، ما هي أفضل طريقة للتعامل مع الخدمة/الكائن الذي تريد ربطه بحيث لا يكون متاحًا عند البدء؟ملحوظة:لست مهتمًا بمعرفة ذلك ببساطة (يمكنك استخدام 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?
}

ربما نحتاج إلى مراقبة NameOwnerChanged على كائن اتصال DBus - ما لم يفعل كود dbus الخاص بـ QT ذلك نيابةً عنا - وبعد ذلك عندما نحصل على حالة تغيير الإشارة، وإذا لزم الأمر، قم بتوصيل الإشارات من الكائن أو فصلها.

جميع الأمثلة التي أجدها إما تتجاهل المشكلة أو تخرج ببساطة إذا كان كائن الخادم غير موجود، ولا تتعامل مع اختفاءه.يلاحظ مثال Car/Controller Qt على الأقل ما إذا كان الخادم قد اختفى ويطبع "Disconnected" إذا أصبح isValid() خطأ أثناء الاستخدام، ولكنه يستقصي 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();
        }
    }
}

لاحظ أن هناك يمكن تكون ظروف السباق مع تنفيذ الأساليب على FooService من داخل ServiceOwnerChanged - لست متأكدًا حتى الآن مما إذا كانت من الآثار الجانبية للربط (dbus-c++ في حالة الاختبار الخاصة بي)، أو متأصلة في تصميم dbus (ممكن - لا الموجود في القائمة البريدية لـ dbus سوف يجيب على السؤال).إن كان هناك يكون حالة سباق حقيقية، يمكنك انتظار إشارة Ready()/أيًا كانت، إذا كنت تتحكم في DBus API.إذا كنت لا تتحكم في الطرف الآخر، فيمكنك إضافة تأخير قصير جدًا أو يمكنك أيضًا مشاهدة AddMatch() للتأكد من أن المالك الجديد قد أضاف تطابقًا على الاسم أيضًا.

نصائح أخرى

ومع كيو تي 5.3، تم إهمال serviceOwnerChanged. استخدام QDBusServiceWatcher الذي يسمح لمشاهدة لخدمة محددة بدلا من كل شيء.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top