Отмена предыдущего вызова dispatch_async

Я реализую механизм отслеживания окна A, следующего за положением окна B. Окно B отправляет события своей позиции, а окно B реагирует на эти события, вызывая setWindowProperties:

void setWindowProperties(bool topMost, bool visible, 
                         CGWindowID parentWindow, CGWindowID aboveWindow, 
                         NSRect windowFrame, NSRect viewFrame, bool isAbove)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        setWindowPropertiesImpl(topMost, visible, parentWindow, aboveWindow, windowFrame, viewFrame, isAbove);
    });
}

Но из-за слишком большого количества событий, отправляемых окном B, я получаю эффект «отслеживания змеи». Я хочу преодолеть это, реагируя только на последнее событие position, то есть отменяя все предыдущие вызовы:

dispatch_async(dispatch_get_main_queue(), ^{
    setWindowPropertiesImpl(topMost, visible, parentWindow, aboveWindow, windowFrame, viewFrame, isAbove);
});

И в результате оставить в очереди только последнее позиционное событие — единственное, что имеет значение.

Мой вопрос: есть ли способ отменить все предыдущие вызовы dispatch_async?


person Sanich    schedule 25.05.2015    source источник


Ответы (2)


Да, задачи отправки теперь можно отменить, но когда есть события, которые поступают быстрее, чем основная очередь может их обработать, иногда полезно использовать источник отправки. В частности, источник данных DISPATCH_SOURCE_TYPE_DATA_ADD.

// create source (and save this reference somewhere so it doesn't get released on you)

dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());

// specify what you want the event handler to do

dispatch_source_set_event_handler(source, ^{
    // whatever you want to do 
});

// start the dispatch source

dispatch_resume(source);

Затем, когда вы хотите вызвать это, вместо того, чтобы делать dispatch_async, вы должны:

dispatch_source_merge_data(source, 1);

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


Для получения дополнительной информации см. видео WWDC 2012 Шаблоны асинхронного проектирования с блоками, GCD и XPC< /а>. В частности, см. шаблон проектирования 8 «Асинхронное обновление состояния» в последней части видео.

person Rob    schedule 25.05.2015

Вы не можете отменить операцию, поставленную в очередь отправки.

Очереди GCD не могут отменить запланированный блок. Архитектура очень похожа на «выстрелил и забыл».

Вместо GCD вы можете использовать NSOperationQueue, который также может выполняться асинхронно, тогда вы можете отменить.

person Bannings    schedule 25.05.2015
comment
Технически задачи отправки теперь можно отменить (см. обсуждение отмены в разделе Power, Performance and Diagnostics). : что нового в GCD и XPC). - person Rob; 25.05.2015
comment
Однако @Rob Cancellation имеет несколько важных предостережений: блок не освобождается к тому времени, когда он будет отменен; Скорее, этот блок по-прежнему должен выполняться очередью, и когда он будет отменен, он будет проигнорирован или пропущен (скорее всего, блок встроен в какую-то функцию-оболочку, которая проверяет наличие флага отмены). Это важно, так как только тогда, когда блок будет запущен и освобожден, будут освобождены захваченные объекты. Обратите внимание, что очереди могут быть приостановлены и могут содержать отмененные блоки. - person CouchDeveloper; 25.05.2015
comment
@CouchDeveloper Это поведение не уникально для GCD (например, если вы используете NSBlockOperation, вы увидите похожее поведение; если вы используете подкласс NSOperation, этот объект не будет освобожден при отмене, а только когда к нему попадет очередь). Но это не имеет значения: я не пытался делать какие-либо заявления о плюсах и минусах повторной отмены в очередях отправки и операций. (На самом деле, я думаю, что вся идея OP об очереди и отмене для быстрых событий нецелесообразна.) Я просто указывал, что этот ответ, хотя и исторически правильный, больше не является строго верным. - person Rob; 25.05.2015