“阻塞”主线程(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... 

我的问题是相互关联的:

1)如果我理解正确,主队列(dispatch_get_main_queue())是一个串行队列。 我用dispatch_semaphore_wait阻塞了主队列/主线程,为什么我在第一个testing用例中看到“我将到达这里,因为currentRunLoop运行了” (对于第二个用例我确定 – 在我的理解中,它应该是什么)?

2)如何阻塞当前正在执行的任务的串行队列可以有下一个任务(哦,这个神秘的runLoop:beforeDate :)在当前解锁之前调度?

我想听听详细全面的答案,因为非常非常非常非常非常依赖于这个问题。

更新:除了被接受的答案,这个SO主题对这个问题有很好的答案: unit testingasynchronous队列的模式,完成时调用主队列

因为主线程上的默认runloop具有特殊的行为,在运行时它也处理主调度队列。 在这种情况下,你实际上并没有阻塞,因为你正在告诉dispatch_semaphore_wait立即超时,它正在做什么(返回非零值,在你的if为真),所以你运行while循环,在那里驱动当前运行循环,因此你的队列被执行。

但是我的答案很广泛,因为我不确定你感到惊讶的是什么。