Reputation: 21808
I've run into an issue I had never seen before. I never thought it might exist. I'm using DFCache
library and in a certain moment dispatch_async
using global queue doesn't execute block.
- (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);
}
});
}
this is how this queue was created:
_processingQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
the queue is never used in any other place. This is not my code. This is the code of DFCache
library. But there's something in my code affecting the queue because it stops working always in a particular moment. I load, save, load, save, load and ... the block is not called. But I can't understand why. I need to know what may cause the block to be not called on dispatch_async
. My code is so big and complex so I don't post it here. What I need is a hint. What specific reason might cause this behaviour? Did you ever see dispatch_async
not calling its block on a global queue? What was causing that?
Upvotes: 2
Views: 2085
Reputation: 2593
In my case, we updated a bunch of third party libraries and this started happening. Pausing the app and analysing the threads, there were a couple instances of TapStream 'internal threads' waiting. I disabled TapStream and this problem disappears. It still doesn't make sense to me why its internal threads would block the global queue...
Upvotes: 0
Reputation: 13999
If you saw "Before calling async ..." in the log message but no "Block called", One possible situation is that all threads were blocked in global queue.
For example, the following code should print "Block called" infinitely, but not.
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)
;
});
}
});
The system prepared a thread pool for global queue. The number of threads in the pool may vary depending on runtime status, anyway, the number of threads are limited. Eventually, all threads would be blocked by the infinite loop.
Thus, your code might have some deadlock, infinite loop, or sort of things blocking global queue threads.
Upvotes: 3
Reputation: 2958
The reason would be like the method(cachedObjectForKey
) is returning before the execution of dispatch_async
.
we can see that
if (object != nil) {
_dwarf_cache_callback(completion, object);
return; // this might be the reason for not calling of dispatch_async
}
there is one more return
in your code, if key.length
is not present.
Hope this helps
Upvotes: 0