我遇到了一个我以前从未见过的问题。我从未想过它可能会存在。我正在使用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
没有在全局队列中调用它的块?造成这种情况的原因是什么?
答案 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,此问题消失了。对我来说仍然没有意义,为什么它的内部线程会阻塞全局队列...