Получить базовую диспетчерскую_катализацию из NSOperationQueue

Кажется, у меня какая-то путаница между очередями dispatch_queue_t и NSOperationQueue.

По умолчанию AFNetworking AFImageRequestOperation выполнит блок обратного вызова успеха в основном потоке приложения. Чтобы изменить это, AFHTTPRequestOperation имеет свойство successCallbackQueue, которое позволяет вам выбрать, в какой очереди запускать обратный вызов.

Я пытаюсь выполнить обратный вызов успеха в той же фоновом потоке/фоновом потоке, который уже выполнил HTTP-запрос. Вместо возврата в основной поток NSOperationQueue, который запускал HTTP запрос должен также запустить обратный вызов, так как есть некоторые тяжелые вычисления, которые мне нужно сделать, используя некоторые из возвращенных изображений.

Моя первая попытка состояла в том, чтобы установить successCallbackQueue в экземпляр NSOperationQueue, на котором запущен AFImageRequestOperation. Однако свойство successCallbackQueue имеет тип dispatch_queue_t, поэтому мне нужен способ получить базовый dispatch_queue_t моего экземпляра NSOperation, если есть такая вещь.

Возможно ли это, или мне нужно создать отдельный dispatch_queue_t?

Причина, по которой я спрашиваю: несколько странно, что AFNetworking наследует от NSOperation, но ожидает, что мы будем использовать очереди dispatch_queue_t для обратных вызовов. Вид смешения двух парадигм dispatch_queue_t и NSOperationQueue.

Спасибо за любые подсказки!

Ответ 1

Нет такой вещи, нет взаимно однозначного соответствия NSOperationQueue и dispatch_queue_t, концепции очередей в двух API очень различны (например, NSOperationQueue не имеет строгой очереди FIFO как GCD).

Единственная очередь отправки, используемая NSOperationQueue для выполнения вашего кода, представляет собой глобальную параллельную очередь приоритета по умолчанию.

Ответ 2

NSOperationQueue не является вашим узким местом с AFNetworking. Операции запроса связаны сетью, а не ЦП или памятью. Вся работа выполняется асинхронно в очередях отправки, доступных в качестве свойств в AFHTTPRequestOperation.

Не рекомендуется использовать сетевой поток для любой обработки. Это никак не улучшит производительность.

Вместо этого, если вы заметили проблемы с производительностью, попробуйте ограничить максимальное количество одновременных операций в очереди операций, чтобы косвенно контролировать объем работы, выполняемой этими очередями фоновой обработки.

Ответ 3

Интересно, что AFHTTPClient использует NSOperationQueue для запуска AFHTTPRequestOperations, но GCD dispatch_queues для обработки результатов.

Что касается NSOperationQueue, документы Apple говорят:

Примечание. В iOS 4 и более поздних версиях операционные очереди используют Grand Central Dispatch для выполнения операций.

но, похоже, нет публичного API, чтобы получить dispatch_queue для данной операции.

Если вам не так важно, чтобы обратный вызов успеха должен был быть в той же очереди/потоке, что и исходная операция, почему бы не установить:

successCallbackQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);

Ответ 4

XCode 6.4 для iOS 8.4, ARC включен

1) "... поэтому мне нужен способ получить базовый dispatch_queue_t моего экземпляра NSOperation, если есть такая вещь".

Существует свойство NSOperationQueue, которое может помочь:

@property(assign) dispatch_queue_t underlyingQueue

Для назначения NSOperationQueue его можно использовать следующим образом:

NSOperationQueue *concurrentQueueForServerCommunication = [[NSOperationQueue alloc] init];
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    concurrentQueueForServerCommunication.underlyingQueue = concurrentQueue;

Или назначить из NSOperationQueue:

NSOperationQueue *concurrentQueueForServerCommunication = [[NSOperationQueue alloc] init];
dispatch_queue_t concurrentQueue = concurrentQueueForServerCommunication.underlyingQueue;

Не уверен, что API, который вы используете для сетевой связи, обновляет ваш интерфейс после завершения сетевой задачи, но на всякий случай, если это не так, вы должны знать, чтобы вернуться в основную очередь при выполнении блока завершения:/p >

dispatch_sync(dispatch_get_main_queue(), ^{

//Update your UI here...

}

Надеюсь, это поможет! Приветствия.

Ответ 5

Прежде всего, это хорошее поведение, чтобы выполнить успех AFImageRequestOperation в основном потоке, потому что основное использование этой операции - загрузить изображение в фоновом режиме и отобразить его в пользовательском интерфейсе (который должен находиться на основной поток), но для того, чтобы удовлетворить потребности этих пользователей (ваш случай тоже), которые хотят выполнить обратный вызов для других потоков, также есть successCalbackQueue.

Итак, вы можете создать свой собственный метод dispatch_queue_t с помощью метода dispatch_queue_create или рекомендованным способом, вы должны использовать dispatch_get_global_queue для получения главной очереди.

В каждом случае убедитесь, что в вашем блоке успеха, если вы вносите некоторые изменения в пользовательский интерфейс, поместите их внутри dispatch_async(dispatch_get_main_queue(), ^{ // main op here});

Ответ 6

Код Swift 3, основанный на ответе @serge-k:

// Initialize the operation queue.
let operationQueue = OperationQueue()
operationQueue.name = "com.example.myOperationQueue"
operationQueue.qualityOfService = .userInitiated

// Initialize a backing DispatchQueue so we can reuse it for network operations.
// Because no additional info is give, the dispatch queue will have the same QoS as the operation queue.
let operationQueueUnderlyingQueue = DispatchQueue(label: "com.example.underlyingQueue")
operationQueue.qualityOfService.underlyingQueue = operationQueueUnderlyingQueue

Затем вы можете использовать это в Alamofire (или AFNetworking) следующим образом:

Alamofire.request("https://example.com/get", parameters: nil).validate().responseJSON(queue: operationQueue.underlyingQueue) { response in
    response handler code
}

Предупреждение здесь, из документации Apple по установке базовой очереди OperationQueue:

Значение этого свойства должно быть установлено только в том случае, если в очереди нет операций; устанавливая значение этого свойства, когда operationCount не равно 0, возникает invalidArgumentException. Значение этого свойства не должно быть значением, возвращаемым dispatch_get_main_queue(). Уровень качества обслуживания, установленный для базовой очереди отправки, переопределяет любое значение, установленное для свойства очереди операций qualityOfService.