Tim*_*Tim 8 multithreading grand-central-dispatch ios
我在后台线程上有一些计算工作,之后我需要更新一些calayer的转换,我试试用
dispatch_async(dispatch_get_main_queue(), ^{calayer.transform = newTransform});
和
CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, ^(void) {calayer.transform = newTransform});
我只是觉得它们是一样的,但是当我使用dispatch_async时,我发现calayer工作得很顺利(可能?).这两个功能有什么不同?
ipm*_*mcc 14
这里的主要区别是CFRunLoopPerformBlock允许您指定执行块的特定运行循环模式,而dispatch_async(dispatch_get_main_queue(),...)仅在常见模式下执行.也许更适合你所看到的性能问题,CFRunLoopPerformBlock并没有唤醒主线程.从以下文档CFRunLoopPerformBlock:
此方法仅将块排入队列,并且不会自动唤醒指定的运行循环.因此,下一次运行循环唤醒以处理另一个输入源时,会执行该块.如果您希望立即执行工作,则必须使用CFRunLoopWakeUp函数明确唤醒该线程.
在实践中,这通常意味着您的块不会被执行,直到运行循环唤醒(即用户事件发生,计时器触发,运行循环源触发,接收到马赫消息等).GCD不是,按设计,基于运行循环的API; 主队列和主线程运行循环之间的关系实际上是一个实现细节.我希望实现唤醒运行循环本身,如果主队列需要服务那么.
如果没有相反的信息,我强烈怀疑这是性能差异的根源.如果您在致电后CFRunLoopWakeUp立即添加电话,我希望性能类似CFRunLoopPerformBlock.
GCD的主队列是串行队列。因此,它一次只能运行一个任务。即使该任务运行内部运行循环(例如,运行模式对话框),提交到主队列的其他任务在该任务完成之前也无法运行。
CFRunLoopPerformBlock()只要运行循环在其中一种目标模式下运行,使用提交的任务就可以运行。这包括运行循环是否从使用提交的任务中运行CFRunLoopPerformBlock()。
考虑以下示例:
CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, ^{
    printf("outer task milestone 1\n");
    CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, ^{
        printf("inner task\n");
    });
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
    printf("outer task milestone 2\n");
});
产生如下输出:
outer task milestone 1
inner task
outer task milestone 2
虽然这样:
dispatch_async(dispatch_get_main_queue(), ^{
    printf("outer task milestone 1\n");
    dispatch_async(dispatch_get_main_queue(), ^{
        printf("inner task\n");
    });
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
    printf("outer task milestone 2\n");
});
产生:
outer task milestone 1
outer task milestone 2
inner task
| 归档时间: | 
 | 
| 查看次数: | 3470 次 | 
| 最近记录: |