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,这个问题就消失了。我仍然不明白为什么它的内部线程会阻塞全局队列...
我 运行 遇到了一个我以前从未见过的问题。我从没想过它可能存在。我正在使用 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,这个问题就消失了。我仍然不明白为什么它的内部线程会阻塞全局队列...