“阻止"主线程(dispatch_get_main_queue())和(或不)定期运行currentRunLoop-有什么区别?
我有以下代码:
- (void)test_with_running_runLoop {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSTimeInterval checkEveryInterval = 0.05;
NSLog(@"Is main queue? : %d", dispatch_get_current_queue() == dispatch_get_main_queue());
dispatch_async(dispatch_get_main_queue(), ^{
sleep(1);
NSLog(@"I will reach here, because currentRunLoop is run");
dispatch_semaphore_signal(semaphore);
});
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW))
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:checkEveryInterval]];
NSLog(@"I will see this, after dispatch_semaphore_signal is called");
}
- (void)test_without_running_runLoop {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSLog(@"Is main queue? : %d", dispatch_get_current_queue() == dispatch_get_main_queue());
dispatch_async(dispatch_get_main_queue(), ^{
sleep(1);
NSLog(@"I will not reach here, because currentRunLoop is not run");
dispatch_semaphore_signal(semaphore);
});
NSLog(@"I will just hang here...");
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW));
NSLog(@"I will see this, after dispatch_semaphore_signal is called");
}
产生以下内容:
Starting CurrentTests/test_with_running_runLoop
2012-11-29 08:14:29.781 Tests[31139:1a603] Is main queue? : 1
2012-11-29 08:14:30.784 Tests[31139:1a603] I will reach here, because currentRunLoop is run
2012-11-29 08:14:30.791 Tests[31139:1a603] I will see this, after dispatch_semaphore_signal is called
OK (1.011s)
Starting CurrentTests/test_without_running_runLoop
2012-11-29 08:14:30.792 Tests[31139:1a603] Is main queue? : 1
2012-11-29 08:14:30.797 Tests[31139:1a603] I will just hang here...
我的问题彼此相关:
-
如果我理解正确,主队列(dispatch_get_main_queue())是一个串行队列.我用dispatch_semaphore_wait阻塞了主队列/主线程,所以为什么在第一个测试用例中看到我会到达这里,因为currentRunLoop正在运行" (第二种情况我可以-在我的理解中,它应该做什么)?
If I understand it right, main queue (dispatch_get_main_queue()) is a serial queue. I block the main queue/main thread with dispatch_semaphore_wait, so why do I see the "I will reach here, because currentRunLoop is run" in the first test case (I'm OK with the second case - in my understanding, it does, what it should)?
已阻塞当前正在执行的任务的 serial 队列如何在解锁当前任务之前分配下一个任务(哦,这个神秘的runLoop:beforeDate:)?
How a serial queue, having current executing task blocked, can have a next task (oh, this mysterious runLoop:beforeDate:) dispatched before the current one is unlocked?
我想听到有关详细和综合的答案,因为非常非常多的事情(在这附近也是如此)都取决于这个问题!
I want to hear detailed and comprehensive answer on this, because very, very much things (here around on SO too) depend on this issue!
更新:除了已接受的答案之外,此SO主题还对以下问题提供了很好的答案:
UPDATE: Besides the accepted answer, this SO topic has good answer to this question: Pattern for unit testing async queue that calls main queue on completion
因为主线程上的默认runloop具有特殊的行为,即它在运行时还会为主调度队列处理.在这种情况下,您实际上并没有阻塞,因为您是在告诉dispatch_semaphore_wait
立即超时(它正在执行超时操作(返回非零值,该值在您的if
中为true))-因此,您将在while循环中运行,其中您驱动当前的运行循环,从而使排队的块得到执行.
Because the default runloop on the main thread has the special behaviour that, when run, it also processes for the main dispatch queue. You're not actually blocking in this case because you're telling dispatch_semaphore_wait
to timeout immediately, which it's doing (returning non-zero, which evaluates in your if
to true) - so you run through your while loop, where you drive the current run loop, and thus your enqueued block gets executed.
但是我的回答很广泛,因为我不确定您对哪一部分感到惊讶.
But my answer is broad because I'm not sure what part you're surprised by.