2012-11-29 50 views
3

我有以下代码:“Block”主线程(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来阻塞主队列/主线程,为什么我会看到“我会到达这里,因为currentRunLoop在第一个测试用例中运行”(我对第二个用例很满意 - 在我的理解中,它确实,它应该如何)?

2)如何一串行队列,其当前执行的任务受阻,可有下一个任务(哦,这个神秘的runLoop:beforeDate :)派出当前一个解锁?

我想听听详细这个综合答案,因为非常非常多的东西(在这里上也是如此)取决于这个问题!

UPDATE:除了公认的答案,这SO主题有很好的回答了这个问题:Pattern for unit testing async queue that calls main queue on completion

回答

5

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

但我的回答很广泛,因为我不确定你感到惊讶的是哪一部分。

+0

“因为主线程上的默认runloop具有特殊行为,所以在运行时它也会处理主调度队列。” 1)我在哪里可以更多地了解这种“特定”行为 - 您能详细描述一下吗? 2)这种行为是否仅限于主队列/线程或任何串行队列/线程 - 其他主比? 3)我的第二个问题:你能描述它是如何应用到主队列,到任何串行队列的?我确认第二个问题足以表达我的意外。 –

+1

它仅适用于主线程/调度队列。请参阅[文档](http://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW15)。 –

相关问题