取消之前调用dispatch_async

时间:2015-05-25 10:27:45

标签: objective-c c macos dispatch-async

我在窗口B的位置之后实现了窗口A的跟踪机制。窗口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 个答案:

答案 0 :(得分:2)

是的,调度任务现在可以取消,但是当事件的进入速度超过主队列可以处理它们时,使用dispatch source有时很有用。特别是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视频Asynchronous Design Patterns with Blocks, GCD, and XPC。具体来说,请参见设计模式8,"异步更新状态"在视频的后半部分。

答案 1 :(得分:0)

您无法取消在调度队列中排队的操作。

  

GCD队列一旦安排就无法取消阻止。这个建筑非常“火上浇油”。#/ p>。

您可以使用也可以异步执行的NSOperationQueue代替GCD,然后您可以取消。