为什么Apple建议在串行后台队列中调度OpenGL命令,这不可避免地会导致崩溃?

ope*_*rog 8 concurrency opengl-es grand-central-dispatch ios

他们建议:

使用GCD时,使用专用的串行队列将命令分派给OpenGL ES; 这可以用来取代传统的互斥模式.

我不明白这个建议.我无法解决这种冲突:

当应用程序的app委托接收到该-applicationWillResignActive调用时,它必须立即停止调用任何OpenGL函数.

如果应用程序在-applicationWillResignActive返回后继续调用OpenGL函数,则应用程序将崩溃.

如果我遵循Apple的建议在串行后台队列中调用OpenGL函数,我面临着这个看似无法解决的问题:

1)收到后-applicationWillResignActive我必须立即停止调用任何进一步的OpenGL函数.

2)但是因为串行队列正处于后台处理代码块的中间,所以有时代码块会完成after -applicationWillResignActive返回,并且应用程序崩溃.

这是显示并发"块"的图示.主线程收到一个完整的停止消息,并且必须阻止进一步调用OpenGL ES.但遗憾的是,这些都发生在后台队列中,这些队列无法在块上工作时停止:

|_____main thread: "STOP calling OpenGL ES!"_____|
 _____|_____drawing queue: "Draw!"_____|_____drawing queue: "Draw!"_____|
Run Code Online (Sandbox Code Playgroud)

从技术上讲,我发现无法立即停止后台队列,并避免在后台进一步调用OpenGL.一旦运行,提交的代码块将继续运行.

我发现的唯一的解决方案是调用OpenGL ES的功能在后台运行.相反,在主线程上调用它们以保证在应用程序失去对GPU的访问权限之后永远不会调用它们.

因此,如果可以在后台调用OpenGL ES函数,那么如何确保在应用程序重新激活后它们永远不会被调用?

Sve*_*ven 7

只需等待applicationWillResignActive队列使用调度组或类似机制完成所有排队操作.

您可以在文档中找到一个示例:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();

// Add a task to the group
dispatch_group_async(group, queue, ^{
   // Some asynchronous work
});

// Do some other work while the tasks execute.

// When you cannot make any more forward progress,
// wait on the group to block the current thread.
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

// Release the group when it is no longer needed.
dispatch_release(group);
Run Code Online (Sandbox Code Playgroud)