为什么dispatch_semaphore_wait()返回的是所有的时间,即使我不滚动?(Why

2019-09-28 17:23发布

布拉德·拉尔森发表了解决方案的CADisplayLink时滚动视图滚动冻结问题。

我的OpenGL ES绘制方法是通过一个名为CADisplayLink ,我试图布拉德的技术,但不能使它工作。 核心问题是,我的OpenGL ES视图是由托管UIScrollView ,并当U IScrollView滚动时, CADisplayLink停止射击。

布拉德描述的技术应该让CADisplayLink继续开火,即使在滚动(将其添加到NSRunLoopCommonModes而不是默认的runloop模式),并且使用一个奇特的信号伎俩呈现回调应该确保它不会渲染时UIKit的太占用。

问题是,虽然信号量伎俩阻止执行回调从图纸,不管是什么。

首先,我创建的串行GCD队列和信号灯initWithFrame我的OpenGL ES查看像这样(在主线程)方法:

frameRenderingQueue = dispatch_queue_create("com.mycompany.crw", DISPATCH_QUEUE_SERIAL);
frameRenderingSemaphore = dispatch_semaphore_create(1);

显示链接被创建并添加到NSRunLoopCommonModes

CADisplayLink *dl = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selector(renderFrame)];
[dl addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

渲染回调执行布拉德的技术:

- (void)renderFrame {
    if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0) {
        NSLog(@"return"); // Gets called ALWAYS!
        return;
    }

    dispatch_async(drawingQueue, ^{
        @autoreleasepool {

            // OpenGL ES drawing code

            dispatch_semaphore_signal(frameRenderingSemaphore);
        }
    });
}

dispatch_semaphore_wait函数总是返回YES ,从而呈现回调从未呈现。 即使我不滚动。

我想,我错过了这里的东西很重要。 有人能指出来?

编辑:看来,只有当我打电话给工作dispatch_sync而不是dispatch_async ,但据布拉德dispatch_async会在这里提供更好的性能。

Answer 1:

我不得不把代码的结构改成这样:

- (void)renderFrame {
    dispatch_async(drawingQueue, ^{
        if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0) {
            return;
        }

        @autoreleasepool {
            // Drawing code...
        }

        dispatch_semaphore_signal(frameRenderingSemaphore);
    });
}

之后我这样重组吧, dispatch_semaphore_wait呼叫停止回是所有的时间。 我不知道这是否只是有效禁止布拉德的信号灯等待招与否。 但是,它的工作原理。



文章来源: Why does dispatch_semaphore_wait() return YES all the time even when I'm not scrolling?