簡體   English   中英

“阻止”主線程(dispatch_get_main_queue())和(或不)定期運行 currentRunLoop - 有什么區別?

[英]"Block" main thread (dispatch_get_main_queue()) and (or not) run currentRunLoop periodically - what is the difference?

我有以下代碼:

- (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:)?

我想聽到關於這個問題的詳細全面的答案,因為非常非常多的事情(在 SO 周圍)都依賴於這個問題!

更新:除了接受的答案,這個 SO 主題對這個問題有很好的回答: Pattern for unit testing async queue that call main queue on completion

因為主線程上的默認 runloop 具有特殊的行為,當運行時,它也為主調度隊列進行處理。 在這種情況下你實際上並沒有阻塞,因為你告訴dispatch_semaphore_wait立即超時,它正在做(返回非零,在你的if中評估為真) - 所以你運行你的 while 循環,在那里你驅動電流運行循環,因此您的入隊塊被執行。

但是我的回答很廣泛,因為我不確定您對哪一部分感到驚訝。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM