如D-Bus文档中所述,所有IPC调用都被视为异步。当Qt通过 QDBusAbstractInterface 调用远程D-Bus对象时,有QBusPendingCall< T>这是完全异步的,并在呼叫完成时提供信令。
在我的应用程序设计中,我想在我的对象适配器上实现异步调用,但是当前的Qt / DBus实现假定所有方法调用都是阻塞的。
所以,有一个问题:是否存在异步实现处理D-Bus方法调用的正确方法?
答案 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()
来请求延迟回复。然后,被调用代码有责任最终向调用者发送回复。
警告:当调用方发出方法调用并等待答复时,它将仅等待有限的时间。打算花很长时间完成的广告位应在文档中清楚说明这一事实,以便呼叫者正确设置更高的超时时间。