2012-11-29 54 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)。 –

相關問題