В интерфейсе API dispatch_*()
нет понятия отмены. Причина этого заключается в том, что почти всегда верно, что ваш код поддерживает концепцию, когда останавливаться или нет, и, следовательно, также поддерживает то, что в диспетчере _ * () API-интерфейсы будут избыточными (а с избыточностью возникают ошибки).
Таким образом, если вы хотите «остановить досрочно» или иным образом отменить ожидающие элементы в очереди отправки (независимо от того, как они были поставлены в очередь), вы делаете это, разделяя некоторый бит состояния с блокированными блоками, который позволяет вам отменить .
if (is_canceled()) return;
Или:
__block BOOL keepGoing = YES;
dispatch_*(someQueue, ^{
if (!keepGoing) return;
if (weAreDoneNow) keepGoing = NO;
}
Обратите внимание, что оба enumerateObjectsUsingBlock:
и enumerateObjectsWithOptions:usingBlock:
поддерживают отмену, потому что этот API находится в другой роли. Вызов метода перечисления является синхронным , даже если фактическое выполнение блоков перечисления может быть полностью параллельным в зависимости от параметров.
Таким образом, установка *stopFlag=YES
заставляет перечисление остановиться. Это, однако, не гарантирует, что оно немедленно прекратится в параллельном случае. Фактически перечисление может выполнить еще несколько уже помещенных в очередь блоков перед остановкой.
(Можно вкратце подумать, что было бы более разумно возвращать BOOL
, чтобы указать, следует ли продолжать перечисление. Для этого потребовалось бы, чтобы блок перечисления выполнялся синхронно, даже в параллельном случае, так что возврат значение можно проверить. Это было бы гораздо менее эффективно.)