dispatch_async块未被调用

时间:2015-02-11 09:26:58

标签: ios objective-c cocoa grand-central-dispatch dispatch-async

我遇到了一个我以前从未见过的问题。我从未想过它可能会存在。我正在使用DFCache库,并且在某个时刻dispatch_async使用全局队列不执行块。

- (void)cachedObjectForKey:(NSString *)key completion:(void (^)(id))completion {
if (!key.length) {
    _dwarf_cache_callback(completion, nil);
    return;
}
id object = [self.memoryCache objectForKey:key];
if (object != nil) {
    _dwarf_cache_callback(completion, object);
    return;
}

NSLog(@"Before calling async %d queue %p", [NSThread isMainThread], _processingQueue);

dispatch_async(_processingQueue, ^{
     NSLog(@"Block called");

    @autoreleasepool {


        id object = [self _cachedObjectForKey:key];
        _dwarf_cache_callback(completion, object);
    }
});

}

这就是这个队列的创建方式:

 _processingQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

队列永远不会在任何其他地方使用。这不是我的代码。这是DFCache库的代码。但是我的代码中有一些东西会影响队列,因为它总是在特定时刻停止工作。我加载,保存,加载,保存,加载......不调用块。但我不明白为什么。我需要知道什么可能导致在dispatch_async上没有调用块。我的代码是如此庞大和复杂,所以我不在这里发布。我需要的是一个提示。具体原因可能导致这种行为?你有没有看到dispatch_async没有在全局队列中调用它的块?造成这种情况的原因是什么?

3 个答案:

答案 0 :(得分:3)

如果您在日志消息中看到“在调用异步...之前”但没有“阻止调用”,则可能的情况是所有线程都在全局队列中被阻止。

例如,以下代码应无限打印“Block called”,但不能打印。

dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(q, ^{
    while (YES) {
        dispatch_async(q, ^{
            NSLog(@"Block called\n");

            // BLOCK THE THREAD
            while (YES)
                ;
        });
    }
});

系统为全局队列准备了一个线程池。池中的线程数可能因运行时状态而异,但无论如何,线程数都是有限的。最终,所有线程都会被无限循环阻塞。

因此,您的代码可能会有一些死锁,无限循环或一些阻塞全局队列线程的事情。

答案 1 :(得分:0)

原因就像方法(cachedObjectForKey)在执行dispatch_async之前返回。 我们可以看到

if (object != nil) {
  _dwarf_cache_callback(completion, object);
   return; // this might be the reason for not calling of dispatch_async
}

如果return不存在,代码中还会有一个key.length

希望这有帮助

答案 2 :(得分:0)

就我而言,我们更新了一堆第三方库,并且这种情况开始发生。暂停应用程序并分析线程,有两个TapStream“内部线程”实例在等待。我禁用了TapStream,此问题消失了。对我来说仍然没有意义,为什么它的内部线程会阻塞全局队列...