dispatch_async 块未调用

dispatch_async block not called

我 运行 遇到了一个我以前从未见过的问题。我从没想过它可能存在。我正在使用 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 上不被调用。我的代码又大又复杂,所以我不 post 在这里。我需要的是一个提示。什么具体原因可能导致这种行为?你见过 dispatch_async 没有在全局队列上调用它的块吗?是什么原因造成的?

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

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

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

希望对您有所帮助

如果您在日志消息中看到 "Before calling async ..." 而没有看到 "Block called",一种可能的情况是全局队列中的所有线程都被阻塞了。

例如,下面的代码应该无限打印 "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)
                ;
        });
    }
});

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

因此,您的代码可能存在一些死锁、无限循环或诸如此类的阻塞全局队列线程的问题。

就我而言,我们更新了一堆第三方库,这开始发生了。暂停应用程序并分析线程,有几个 TapStream 'internal threads' 实例在等待。我禁用了 TapStream,这个问题就消失了。我仍然不明白为什么它的内部线程会阻塞全局队列...