我正在开发一个iOS应用程序,例如单击按钮,它会启动多个线程,每个线程执行一段Open GL代码。这些线程要么设置了不同的EAGLContext,要么如果它们使用相同的EAGLContext,那么它们就会同步(即2个线程不会并行设置相同的EAGLContext(。
现在假设应用程序进入后台。根据Apple的文档,我们应该在回调中停止所有OpenGL调用applicationWillResignActive:
以便在调用applicationDidEnterBackground:
时不再进行GL调用。
我正在使用dispatch_queues
来创建后台线程。例如:
__block Byte* renderedData; // some memory already allocated
dispatch_sync(glProcessingQueue, ^{
[EAGLContext setCurrentContext:_eaglContext];
glViewPort(...)
glBindFramebuffer(...)
glClear(...)
glDrawArrays(...)
glReadPixels(...) // read in renderedData
}
use renderedData for something else
我的问题是 - 如何处理applicationWillResignActive:
以便任何此类后台 GL 调用不仅可以停止,还可以在applicationDidBecomeActive:
上恢复?我应该等待当前正在运行的块完成后再从applicationWillResignActive:
返回吗?还是我应该暂停glProcessingQueue
并返回?
我还读到,当应用程序以其他方式中断时,情况类似,例如显示警报、电话等。
我可以在任何时间点有多个这样的线程,可能由多个 ViewController 调用,所以我正在寻找一些可扩展的解决方案或设计模式。
在我看来,你需要暂停一个线程或杀死它。
如果你杀死它,你需要确保释放所有资源,这意味着最有可能再次调用openGL。在这种情况下,实际上最好只是等待块完成执行。这意味着块不能花太长时间才能完成,这是无法保证的,并且由于您有多个上下文和线程,因此实际上可能会出现问题。
所以暂停似乎更好。我不确定是否有直接的 API 来暂停线程,但您可以让它等待。也许类似于这个系统的s系统可以提供帮助。
链接的示例似乎完全处理了您想要的内容;它已经检查了当前线程并锁定了该线程。我想你可以把它打包到一些工具中作为静态方法或 C 函数,只要你有信心可以暂停线程,你就会简单地做一些事情:
dispatch_sync(glProcessingQueue, ^{
[EAGLContext setCurrentContext:_eaglContext];
[ThreadManager pauseCurrentThreadIfNeeded];
glViewPort(...)
glBindFramebuffer(...)
[ThreadManager pauseCurrentThreadIfNeeded];
glClear(...)
glDrawArrays(...)
glReadPixels(...) // read in renderedData
[ThreadManager pauseCurrentThreadIfNeeded];
}
如果使用主线程,您可能仍会遇到问题。您可能希望跳过暂停,否则您的系统可能永远不会再次唤醒(但不确定,请尝试一下(。
所以现在你看到你的ThreadManager
的界面是这样的:
+ (void)pause {
__threadsPaused = YES;
}
+ (void)resume {
__threadsPaused = NO;
}
+ (void)pauseCurrentThreadIfNeeded {
if(__threadsPaused) {
// TODO: insert code for locking until __threadsPaused becomes false
}
}
让我们知道您的发现。