在Qt / DBus适配器中实现异步功能的正确方法

时间:2016-08-11 05:13:25

标签: c++ qt c++11 asynchronous qdbus

如D-Bus文档中所述,所有IPC调用都被视为异步。当Qt通过 QDBusAbstractInterface 调用远程D-Bus对象时,有QBusPendingCall< T>这是完全异步的,并在呼叫完成时提供信令。

在我的应用程序设计中,我想在我的对象适配器上实现异步调用,但是当前的Qt / DBus实现假定所有方法调用都是阻塞的。

所以,有一个问题:是否存在异步实现处理D-Bus方法调用的正确方法?

1 个答案:

答案 0 :(得分:0)

Declaring Slots in D-Bus Adaptors中对此进行了很好的解释。

我们通过编写一个以持久结构存储请求数据的插槽来做到这一点,并使用QDBusMessage::setDelayedReply(true)向调用方指示响应将在以后发送。

struct RequestData
{
    QString request;
    QString processedData;
    QDBusMessage reply;
};

QString processRequest(const QString &request, const QDBusMessage &message)
{
    RequestData *data = new RequestData;
    data->request = request;
    message.setDelayedReply(true);
    data->reply = message.createReply();
    QDBusConnection::sessionBus().send(data->reply);

    appendRequest(data);
    return QString();
}

需要使用QDBusConnection::sessionBus().send(data->reply)来明确告知呼叫者响应将被延迟。在这种情况下,返回值并不重要。我们返回一个任意值来满足编译器的要求。

在处理请求并提供答复时,应使用获取的QDBusMessage对象发送请求。在我们的示例中,回复代码可能如下所示:

void sendReply(RequestData *data)
{
    // data->processedData has been initialized with the request's reply
    QDBusMessage &reply = &data->reply;

    // send the reply over D-Bus:
    reply << data->processedData;
    QDBusConnection::sessionBus().send(reply);

    // dispose of the transaction data
    delete data;
}

从示例中可以看出,当延迟答复到位时,Qt D-Bus将忽略来自插槽的返回值。它们仅用于在将适配器的描述传达给远程应用程序时,或者在插槽中的代码决定不使用延迟答复的情况下,确定插槽的签名。

Qt D-Bus通过在原始消息上调用QDBusMessage::reply()来请求延迟回复。然后,被调用代码有责任最终向调用者发送回复。

警告:当调用方发出方法调用并等待答复时,它将仅等待有限的时间。打算花很长时间完成的广告位应在文档中清楚说明这一事实,以便呼叫者正确设置更高的超时时间。