Правильный способ реализации асинхронной функции в адаптере Qt/DBus
Как описано в документации по D-Bus, все вызовы IPC считаются асинхронными. Когда Qt вызывает удаленный объект D-Bus через QDBusAbstractInterface, есть QBusPendingCall
В моем проекте приложения я хочу реализовать асинхронный вызов на моем объектном адаптере, но текущая реализация Qt/DBus предполагает, что все вызовы методов блокируются.
Итак, возникает вопрос: существует ли правильный способ реализовать обработку вызова метода D-Bus асинхронно?
0 ответов
Это довольно хорошо объясняется в разделе "Объявление слотов в адаптерах D-Bus".
Мы делаем это, записывая слот, в котором данные запроса хранятся в постоянной структуре, указывая вызывающему с помощью 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()
в исходном сообщении. Затем вызываемый код отвечает за отправку ответа вызывающему абоненту.
Предупреждение: когда вызывающий абонент выполняет вызов метода и ждет ответа, он будет ждать только ограниченное время. Слоты, для завершения которых требуется много времени, должны четко указать этот факт в документации, чтобы вызывающие абоненты правильно устанавливали более высокие таймауты.