GCD和回调 - 并发问题

Z S*_*Z S 6 grand-central-dispatch abaddressbook ios4

我注册了一个回调处理程序,用于侦听iOS通讯簿中的更改.由于一些奇怪的原因(已经提交了一个错误),当应用程序从后台返回时,有时可以多次调用此回调.我希望我的回调处理程序只运行一次逻辑,即使在多次调用回调的情况下也是如此.这是我注册回调的方式:

ABAddressBookRegisterExternalChangeCallback(address_book, adressBookChanged, self);
Run Code Online (Sandbox Code Playgroud)

这就是我构建回调处理程序以利用GCD来处理这个问题的方法.不幸的是,它不起作用,并且GCD不会阻止内部逻辑被调用两次......

void adressBookChanged(ABAddressBookRef ab, CFDictionaryRef info, void 
                       *context) 
{ 
    NSLog(@"** IN addressBookChanged callback!");

    ABAddressBookUnregisterExternalChangeCallback (ab, adressBookChanged, context);

    __block BOOL fireOnce = FALSE;
    dispatch_queue_t queue;
    queue = dispatch_queue_create("com.myapp.abcallback", NULL);

    dispatch_async(queue, ^{

        if (fireOnce == FALSE) {

            fireOnce = TRUE;

            dispatch_queue_t queueInternal;
            queueInternal = dispatch_queue_create("com.myapp.abcallbackInternal", NULL);
            dispatch_async (queueInternal, ^{
               NSLog(@"do internal logic");

            });

            dispatch_release(queueInternal);
        }
    });
    dispatch_release(queue);
}
Run Code Online (Sandbox Code Playgroud)

我很确定这段代码可以用于接收多个通知,那么回调会有所不同吗?它们是否自动生成不同的线程,每次使fireOnce值为FALSE?我应该如何编写此代码以防止多次回调多次调用内部逻辑?我想我可以使用锁和/或同步块来实现这一点,但GCD似乎是一种更清晰的方法来实现这一目标.

Z S*_*Z S 2

我最终使用 NSTimers 而不是 GCD 来防止重复回调触发我的关键方法。更简单,而且效果很好!

[self.changeTimer invalidate];
self.changeTimer = nil;
self.changeTimer = [NSTimer scheduledTimerWithTimeInterval:3.0
                                                            target:self
                                                          selector:@selector(handleAdressBookExternalCallbackBackground)
                                                          userInfo:nil
                                                           repeats:NO];
Run Code Online (Sandbox Code Playgroud)