【问题标题】:How to tear down a GCD queue?如何拆除 GCD 队列?
【发布时间】:2012-09-26 17:01:52
【问题描述】:

我有一个 GCD 绘图队列来更新我的 OpenGL ES 场景,其结构如下:

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

        @autoreleasepool {
            [self startDrawing];

            // drawing code

            [self endDrawing];
        }

        dispatch_semaphore_signal(frameRenderingSemaphore);
    });
}

当应用退出活动或进入后台(两者)时,我通过使 CADisplayLink 无效来停止 OpenGL 绘图运行循环。

然而,问题是即使在 CADisplayLink 失效之后,dispatch_asyn 仍会调度绘图块。当用户按下主页按钮时,我的应用程序崩溃,因为它试图在 OpenGL 中绘制一个框架,即使 iOS 已经拆除了上下文。

有没有办法杀死/暂停 GCD 队列,使其不再分派任何东西?

【问题讨论】:

  • dispatch_suspend 将阻止其他排队的作业开始,但对当前正在运行的作业不做任何事情。 (我不知道这两种情况中的哪一种适用于此。)
  • 除了Simon的建议,我可能会指出你的dispatch_semaphore_wait()放错地方了。它需要在dispatch_async() 之前,而不是在您的异步块中。您使用这样的信号量的全部原因是为了防止一次在您的 GCD 队列上添加多个渲染块,而您在应用程序进入后台后看到渲染的帧的原因是因为一堆他们已经堆积在您的队列中。我敢打赌,在将等待移到异步调度之前,您会发现这种崩溃消失了。

标签: ios opengl-es concurrency grand-central-dispatch


【解决方案1】:

我认为最简单的方法是在应用程序中设置一个标志,在执行块之前检查它。例如:

- (void)drawFrame {
    dispatch_async(drawingQueue, ^{

        if (appIsTerminated || appIsInBackground) {
            return;
        }

        if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0) {
            return;
        }

        @autoreleasepool {
            [self startDrawing];

            // drawing code

            [self endDrawing];
        }

        dispatch_semaphore_signal(frameRenderingSemaphore);
    });
}

您可以在applicationDidEnterBackground 和applicationWillTerminate 中的应用委托中设置这些值。

你也可以试试这个:

dispatch_suspend(drawingQueue);
dispatch_release(drawingQueue);

虽然不太确定。

这里是所有详细信息:https://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html

【讨论】:

  • dispatch_release 仅减少队列的保留计数,允许在保留计数达到零时释放它,因此这不太可能帮助 iFrog。 dispatch_suspend 更有希望,但取决于块是否已经在运行。 (如果还没有运行,你上面的解决方案可能更简单。)
  • 谢谢!点赞需要 15 声望。会做到的:-)
  • 你现在应该可以了! :)
猜你喜欢
  • 1970-01-01
  • 2012-09-01
  • 2016-06-04
  • 1970-01-01
  • 2013-10-11
  • 2020-01-09
  • 2019-08-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多