Отмена предыдущего вызова 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, я получаю эффект "отслеживания змей". Я хочу преодолеть это, реагируя только на последнее событие позиции, то есть отменив все предыдущие вызовы:
dispatch_async(dispatch_get_main_queue(), ^{
setWindowPropertiesImpl(topMost, visible, parentWindow, aboveWindow, windowFrame, viewFrame, isAbove);
});
И в результате, оставляя в очереди только последнее событие позиции - единственное, что имеет значение.
Мой вопрос: есть ли способ отменить все предыдущие звонки на dispatch_async
?
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 "Асинхронное обновление состояния" в последней части видео.
Вы не можете отменить операцию, поставленную в очередь в очереди отправки.
Очереди GCD не могут отменить блок, как только он запланирован. Архитектура очень сильно "огонь и забудь".
Вместо GCD вы можете использовать NSOperationQueue, который также может выполнять асинхронное выполнение, затем вы можете отменить.