Как использовать результаты обратного вызова в асинхронной модели C

#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"
}