2013-09-12 2 views

ответ

0

GCD не реализует API отмены, поскольку он не был бы безопасным (он мог бы прервать работу в середине). Если вы хотите отменить задачи, вам нужно сделать это самостоятельно, выполнив «отмененный» логический процесс и проверив его в своих задачах, когда они начнутся, а затем периодически.

+0

Я знаю, что вы имеете в виду небезопасно, но NSOperationQueue поддерживает «отмена», чтобы отменить эти блоки еще не начали. очередь отправки должна поддерживаться, как эта функция, почему бы и нет? – Richard

10

Как упоминает @HampusNilsson, вы не можете разумно отменить любую операцию в полете в среде, не связанной с мусором (например, это), потому что она по своей сути будет утечка ресурсов и оставит процесс в неопределенном состоянии. NSOperationQueue имеет API отмены, и этот API может использоваться для осуществления отмены операций в полете, при условии, что сами операции совместно проверяют флаг, а затем очищают и возвращают на ранней стадии. Это не правда, трудно прервать.

Что касается отмены рабочих элементов, но не начатых, да, NSOperationQueue справляется с этим, но это происходит за счет дополнительных расходов, а NSOperationQueue - это более высокий уровень абстракции. Производительность GCD в основном основывается на внутреннем использовании незакрепленных очередей. Остановка без блокировки будет быстрее, чем реализация на основе блокировки, но для достижения этой скорости потребуются определенные компромиссы. Например, я ожидал бы, что будет намного сложнее произвольно мутировать очередь в режиме блокировки, чтобы удалить отмененную операцию. Я подозреваю, что ограничение операций открытой очереди на «только в очереди» и создание неизменяемых рабочих элементов (блоки и функции ptrs) открыло дверь для многих оптимизаций, которые позволяют GCD иметь такие небольшие накладные расходы и работать так хорошо.

FWIW, в общем случае, операции по отмене транзакции довольно тривиальны для реализации поверх существующего API GCD, поэтому любой, кто нуждается в этой функции, может довольно легко сделать это сам (и, вероятно, таким образом, что это лучше подходит к их конкретным потребностям, чем обобщенный API). Рассмотрим следующую функцию - он ставит в очередь блок в очереди и возвращает блок, который вы могли бы назвать позже отменить операцию: в очереди

dispatch_block_t dispatch_cancelable_async(dispatch_queue_t q, dispatch_block_t b) 
{ 
    __block uintptr_t isCancelled = 0; 
    dispatch_async(q, ^{ 
     if (!isCancelled) b(); 
    }); 
    return [[^{ isCancelled = 1; } copy] autorelease]; 
} 

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

«Используйте абстракцию высочайшего уровня, которая выполняет свою работу». Если вы хотите отменить, и разница в накладных расходах между NSOperationQueue и GCD не является существенным фактором, вы должны просто использовать NSOperationQueue. Некоторые даже догадываются, что использование NSOperationQueue является более идиоматическим выбором при работе в Objective-C. Помимо этого, реализация отмены без отмены для общего случая поверх GCD является, как показано, достаточно тривиальной.

Исходя из всего этого, мое подозрение в том, что здание в отмене API не было целесообразным компромиссом с точки зрения производительности и сложности.

0

с прошивкой 8 и выше, вы можете отменить выполнение блока с
dispatch_block_cancel

dispatch_block_t blockTask = dispatch_block_create(0,{ 
//do some task 
}); 
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,5*NSEC_PER_SEC); 
dispatch_after(time,dispatch_get_main_queue(),blockTask); 

dispatch_block_cancel(blockTask); 
Смежные вопросы