#c
#c
Вопрос:
У меня есть C API, который имеет определенные определенные функции и связанные с ним обратные вызовы. Все эти функции являются асинхронными по своей природе.
Теперь, используя этот API, я хочу создать асинхронную систему, которая отправляет несколько запросов на сервер для сбора различных элементов данных, а затем использует эти элементы данных для дальнейшего использования.
Например:
void functionA()
{
requestDataForA(); //asynchronous request to the server
//async wait for the callback
processDataForA();
}
void functionB()
{
requestDataForB(); //asynchronous request to the server
//async wait for the callback
processDataForB();
}
void functionC()
{
requestDataForC(); //asynchronous request to the server
//async wait for the callback
processDataForC();
}
Теперь мой вопрос заключается в том, что, когда обратный вызов выдает элемент данных, как его использовать для последующей обработки. Это невозможно сделать в обратном вызове, поскольку обратный вызов не знает, кто будет использовать данные.
Спасибо
, Шив
Ответ №1:
У вас неявно есть эта информация, вам просто нужно ее отслеживать. Допустим, что объект A
вызывает functionA
, вы должны A
реализовать определенный интерфейс, который принимает данные, связанные с ответом от вызова requestA
. Допустим, этот ответ DataA
, тогда интерфейс будет
class InterfaceADataHandler
{
public:
virtual void handle(DataA constamp;) = 0; // this is the method that will process the data..
};
class A : public InterfaceADataHandler
{
public:
void handle(DataA constamp;) {} // do something with data
// Now I want to be called back
void foo()
{
functionA(this); // call function A with this instance
}
};
void functionA(InterfaceADataHandler* pHandler)
{
// store this handler against request (say some id)
request..();
// wait for callback
// when you have callback, lookup the handler that requested the data, and call that handler
}
Комментарии:
1. Когда вы говорите, что обработчик хранилища соответствует запросу, что это значит? Кроме того, я не хочу ждать обратного вызова, так как тем временем хочу заняться другими делами. Скажем, я запрашиваю данные и начинаю делать что-то еще. Теперь, когда обратный вызов готов, он должен каким-то образом поставить функцию в очередь для выполнения на основе результата.
2. @shivchawla, допустим, что можно вызывать
requestA
несколько раз — как бы вы связали каждый обратный вызов с каждым запросом? Вы можете назначить некоторое число — скажем, идентификатор запроса для каждого запроса. Итак, у вас есть карта (напримерmap<request_id, InterfaceADataHandler*>
), теперь ваш API внутренне будет иметь обработчик обратногоrequestA
вызова, в этом обработчике вы найдете реальный обработчик для вызова из карты выше на основе request_id и вызовите его.3. Если мне нужно запросить несколько элементов данных, прежде чем я начну какую-то реальную работу, то это сопоставление не будет работать, поскольку будет несколько функций обратного вызова. Таким образом, обработчик для составных асинхронных операций — это то, что может решить эту проблему. Каким-то образом все промежуточные запросы должны быть подключены к одному и тому же обработчику завершения.
Ответ №2:
В большинстве API вы, разработчик, будете предоставлять обратный вызов, который будет вызываться API с данными, которые были получены. Затем вы можете сохранить данные и использовать их позже или использовать их в обратном вызове (при условии, что обработка не займет много времени и вы обещаете не блокировать ввод-вывод).
Модель будет выглядеть больше как:
void functionA()
{
requestDataForA(processDataForA); //asynchronous request to the server
}
void processDataForA(void *someData)
{
// process "someData"
}