Убивать элементы в очереди 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() очередь сразу после ее возобновления.