Как очистить и полностью освободить очередь Grand Central Dispatch при выпуске?


У меня есть объект, который при инициализации создает последовательную очередь GCD, используя dispatch_queue_create, а при освобождении вызывает dispatch_free. Во время существования объекта в очередь добавляются блоки отправки, однако очередь также останавливается и запускается с помощью dispatch_suspend и dispatch_resume.

Моя проблема заключается в том, что в какой-то момент объект может быть освобожден, и когда он будет освобожден, я хотел бы, ради чистоты, полностью отбросить очередь отправки и все dispatch_block_t объекты в ней, независимо от того, есть ли они. или очередь не приостанавливается.

Как я понимаю, очередь не будет освобождаться до тех пор, пока она больше не будет "нужна" в том смысле, что она больше не удерживается блоками отправки внутри нее. Это приводит меня к мысли, что для освобождения очереди, я должен очистить ее, позволив блокам в ней сначала выполнить завершение. Какой самый простой и надежный способ сделать это?
1 3

1 ответ:

Как правило, это не то, о чем вам следует слишком сильно беспокоиться. Из управление памятью для диспетчерских очередей в руководстве по программированию параллелизма:

Вы можете использовать функции dispatch_retain и dispatch_release для увеличения и уменьшения количества ссылок по мере необходимости. Когда счетчик ссылок очереди достигает нуля, система асинхронно освобождает очередь.

Поэтому, когда вы вызываете dispatch_release(myQueue), вы понижаете количество удерживаемых, но все равно какие-либо задачи на очереди будет сохранение очереди. Только после того, как они закончатся, счетчик удержания очереди будет равен 0. Итак, эта часть вашего вопроса:

Это приводит меня к мысли, что для освобождения очереди, я должен очистить ее, позволив блокам внутри нее сначала выполнить завершение.

Точно. Если у вас есть задачи, которые вы не хотите выполнять, которые находятся в очереди, продолжайте читать.

Если вы приостанавливаете и возобновляете очередь из вашего кода, это не вызывает проблем-потому что вы должны сбалансировать все приостановленные и возобновленные вызовы. Если вы оставите свою очередь в подвешенном состоянии, у вас будет плохое время. Тем не менее, у вас также есть возможность установить функцию очистки для очереди, используя dispatch_set_finalizer_f . Это не должно быть необходимо, но оно есть, если вам это нужно.

Теперь, основываясь на том, что вы описываете здесь, я бы предложил вместо этого использовать NSOperation и NSOperationQueue. Это слой более высокого уровня поверх GCD, который позволяет вам отмените задания и сделайте некоторые другие полезные вещи, которые гораздо труднее сделать, используя GCD напрямую.