2015-05-25 7 views
0

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

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, я получаю эффект «отслеживания змеи». Я хочу, чтобы получить над ним путем взаимодействия только к последнему событию позиции, а это означает, отменяя весь предыдущий вызов:

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

И как результат, в результате чего в очереди только последнее событие положения - только одно, что имеет значение ,

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

ответ

0

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

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

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

+0

Технически задачи отправки теперь можно отменить (см. Обсуждение отмены в [Power, Performance and Diagnostics: Что нового в GCD и XPC] (https://developer.apple.com/videos/wwdc/2014/?id=716)). – Rob

+0

@Rob Отмена имеет некоторые важные оговорки: блок не освобождается к моменту его отмены; Скорее, этот блок по-прежнему требуется для выполнения очереди, и когда он отменяется, он будет «проигнорирован» или «обойден» (скорее всего, блок встроен в некоторую функцию-обертку, которая проверяет флаг отмены). Это важно, так как только тогда, когда блок был запущен и выпущен, захватываемые объекты будут выпущены. Обратите внимание, что очереди могут быть приостановлены и могут содержать отмененные блоки. – CouchDeveloper

+0

@CouchDeveloper Это поведение не уникально для GCD (например, если вы используете 'NSBlockOperation', вы увидите подобное поведение, если вы используете подкласс NSOperation, этот объект не будет освобожден при аннулировании, но только тогда, когда очередь дойдет до Это). Но это не имеет значения: я не пытался заявлять о каких-либо претензиях на отмену «за» и «против» в диспетчерах и операционных очередях. (На самом деле, я думаю, что вся идея OP о «очереди и отмене» для быстрых событий нецелесообразна.) Я просто указывал, что этот ответ, хотя и исторически правильный, больше не является верным. – Rob

2

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

// 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 Asynchronous Design Patterns with Blocks, GCD, and XPC. В частности, см. Шаблон дизайна 8, «Состояние обновления асинхронно» в последней части видео.

+0

от вас пример.Как вы отменяете предыдущие звонки? – user2924482

+0

Если события происходят быстро, я предлагаю не отменять, а использовать источник добавления отправки/слияния, как показано выше, который будет коалесцировать обновления со скоростью, с которой может работать пользовательский интерфейс. Но если вы хотите отменить отправленный блок кода, см. Https://stackoverflow.com/a/38372384/1271826 для Swift. Для воспроизведения Objective-C я могу отнести вас к оригинальному видео WWDC, в котором показано, как отменить рассылаемые блоки, [Power, Performance and Diagnostics: Whats, новичок в GCD и XPC] (https://developer.apple.com/videos/ play/wwdc2014/716 /), около 20 минут в видео. – Rob