Убивать элементы в очереди dispatch_async в iOS
Я запускаю кучу элементов в фоновом режиме, используя dispatch_async, и иногда я хочу убить то, что у меня есть в очереди, - возможно ли это? Например, этот код запускается в представлении, а затем пользователь возвращает экран. Все эти запущенные действия продолжают работать независимо от обратной навигации. В идеале я хотел бы убить эти элементы:
dispatch_async(dispatch_get_global_queue(2, 0), ^{
for (int i=0; i<[self.manufacturers count]; i++) {
NSString *manufacturerID = [[[self.manufacturers objectAtIndex:i] ManufacturerID] stringValue];
[self doSync:manufacturerID withIndex:i setTimer:YES];
}
});
Если я создаю очередь и назову ее, а затем отпустите ее в dealloc вид, который вызывается, они продолжают работать.
Ответы
Ответ 1
В диспетчерских очередях для завершения не существует явного положения. Чтобы сделать это, несколько обычным является проверка места выхода для определения завершения. В принципе, это был бы семафор.
NSOperationQueue
(абстракция более высокого уровня, но все же построенная с использованием GCD внизу) имеет поддержку для отмены операций. Так, например, вы можете создать серию NSOperations и добавить их в NSOperationQueue, а затем сообщение -cancelAllOperations
в очередь, когда вам это не понадобится.
Большая часть выбранной вами архитектуры будет зависеть от того, сколько из них работает и есть ли у них разные триггеры. Среди реализаций NSOperation, скорее всего, является "самым чистым" решением, поскольку у вас есть произвольная очередь, на которую вы можете следить за завершением операций, и вы также можете отменить выдающиеся операции. Дальше по шкале взлома будет неустойчивое местоположение, в котором каждый из этих блоков будет смотреть внутри жесткой петли, чтобы определить, не закончится ли они преждевременно. Еще ниже будет глобальная переменная для одной и той же базовой функции.
В конце концов, даже реализация NSOperation включает в себя тест для выхода в последовательном местоположении (поскольку только убийство потока может привести к несогласованности в данных, которыми управляют или в распределении/перенаправлении).
Ответ 2
Лучший способ сделать это - создать свою собственную параллельную очередь (не использовать одну из глобальных), а затем вызвать dispatch_suspend() в очереди, когда вы хотите прекратить ее обрабатывать. В этот момент прочтите следующее: Очереди отправки: как узнать, запущены ли они и как их остановить
Использование флага отмены позволит вам возобновить очередь таким образом, чтобы все остальные блоки в основном просто выходили (после выполнения любого управления памятью, которое они должны делать, например, освобождения ресурсов), когда вы снова возобновляете его. Вы также можете отправить_release() очередь сразу после ее возобновления.