objective-c - "Block"主线程 (dispatch_get_main_queue()) 和(或不)定期运行 currentRunLoop - 有什么区别?

标签 objective-c ios queue semaphore nsrunloop

我有以下代码:

- (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 calls main queue on completion

最佳答案

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

但我的回答很笼统,因为我不确定您对哪一部分感到惊讶。

关于objective-c - "Block"主线程 (dispatch_get_main_queue()) 和(或不)定期运行 currentRunLoop - 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13620128/

相关文章:

c - 不带 if 的队列入队函数

oracle - 如何清除 Oracle AQ 中的队列

objective-c - 在 ImageView 中将数组绘制为图形

iphone - 我会丢失带有新证书的钥匙串(keychain)吗?

objective-c - 我应该将 =variable 分配给 UIButton 或 UILabel 属性吗?

ios - Swift 中的核心数据 : Only saving last object in a for loop

objective-c - Xcode 4 中未声明的结构地址信息

objective-c - Swift 如何在单行上编写语句

ios - CocoaPods - 自定义动态框架 - 无法获取最新版本的框架

php - 有没有好的PHP脚本运行框架推荐?基于队列的脚本触发器