Правильный способ реализации асинхронной функции в адаптере 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()в исходном сообщении. Затем вызываемый код отвечает за отправку ответа вызывающему абоненту.

Предупреждение: когда вызывающий абонент выполняет вызов метода и ждет ответа, он будет ждать только ограниченное время. Слоты, для завершения которых требуется много времени, должны четко указать этот факт в документации, чтобы вызывающие абоненты правильно устанавливали более высокие таймауты.

Другие вопросы по тегам