首页 文章

“阻塞”主线程(dispatch_get_main_queue())和(或不)定期运行currentRunLoop - 有什么区别?

提问于
浏览
3

我有以下代码:

- (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来阻塞主队列/主线程,所以为什么我在第一个测试用例中看到了"I will reach here, because currentRunLoop is run"(我对第二种情况没问题 - 根据我的理解,确实如此,它应该是什么)?

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

我希望听到关于此的详细而全面的答案,因为非常非常多的东西(这里也是如此)依赖于这个问题!

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

1 回答

  • 6

    因为主线程上的默认runloop具有特殊行为,在运行时,它还会处理主调度队列 . 你're not actually blocking in this case because you'告诉 dispatch_semaphore_wait 立即超时,它正在做(返回非零,在你的 if 中评估为真) - 所以你运行你的while循环,你驱动当前的运行循环,从而你的排队块被执行 .

    但我的答案很广泛,因为我不确定你对哪一部分感到惊讶 .

相关问题