如 D-Bus 文档中所述,所有 IPC 调用都被视为异步调用。当 Qt 通过QDBusAbstractInterface调用远程 D-Bus 对象时,QBusPendingCall<T> 是完全异步的,并在调用完成时提供信号。
在我的应用程序设计中,我想在我的对象适配器上实现异步调用,但当前的 Qt/DBus 实现假定所有方法调用都是阻塞的。
所以,有一个问题:是否有适当的方法来实现异步处理 D-Bus 方法调用?
如 D-Bus 文档中所述,所有 IPC 调用都被视为异步调用。当 Qt 通过QDBusAbstractInterface调用远程 D-Bus 对象时,QBusPendingCall<T> 是完全异步的,并在调用完成时提供信号。
在我的应用程序设计中,我想在我的对象适配器上实现异步调用,但当前的 Qt/DBus 实现假定所有方法调用都是阻塞的。
所以,有一个问题:是否有适当的方法来实现异步处理 D-Bus 方法调用?
这在Declaring Slots in D-Bus Adapters 中有很好的解释。
为此,我们编写了一个将请求数据存储在持久结构中的槽,向调用者指示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 忽略。它们仅用于在将适配器的描述传达给远程应用程序时确定插槽的签名,或者在插槽中的代码决定不使用延迟回复的情况下。
QDBusMessage::reply()
通过调用原始消息从 Qt D-Bus 请求延迟回复本身。然后,被调用代码负责最终向调用者发送回复。
警告:当调用者发出方法调用并等待回复时,它只会等待有限的时间。打算花费很长时间才能完成的插槽应在文档中明确说明这一事实,以便调用者正确设置更高的超时时间。