我们正在构建一个内容编辑器,在NSWindow
中为了测试目的而调出一个“cocos Player”。用户可以测试一些内容,然后关闭窗口。
所以我需要能够关闭cocos并在同一个应用程序中重新启动。
如果我使用CC_MAC_USE_DISPLAY_LINK_THREAD
线程模型,一切正常。我必须在CCDirectorMac
中修复才能使其正常工作。在CCDirectorMac | stopAnimation
中,我必须将_runningThread
设置为nil
,因为#if
和#elif
在使用CC_MAC_USE_DISPLAY_LINK_THREAD
时未将其设置为nil。
无论如何,现在我能够“结束”导演,然后在没有问题的情况下重新开始导演。
我的问题是:如果我正在构建一个AppKit编辑器,偶尔使用cocos2D我的线程模型真的是CC_MAC_USE_MAIN_THREAD
,如文档中所建议的那样?
当我使用CC_MAC_USE_MAIN_THREAD
时,我会在stopAnimation
的行中找到 HANG :
CVDisplayLinkStop(displayLink);
我认为主线程很好,可以避免我们工具的线程问题。性能不是问题。我找不到任何关闭并重新启动NSWindow
中cocos2d的示例代码......所以我的假设是我在未经测试的水域(或经过少量测试的水域)。
我关闭/重启的步骤是:
[[CCDirector sharedDirector] end]
stopAnimation
对于Mac桌面应用程序的线程模型的任何建议......以及CVDisplayLinkStop
挂起的原因将不胜感激。
提前致谢。
答案 0 :(得分:3)
好的,我在阅读这篇文章及其在Apple邮件列表上的答案后想出来了:http://lists.apple.com/archives/quartz-dev/2006/Oct/msg00056.html
使用CC_MAC_USE_MAIN_THREAD
时,显示链接线程使用performSelector:onThread:waitUntilDone:
在主线程上运行drawScene:
。它为YES
参数传递waitUntilDone:
,因此显示链接线程阻止,直到主线程可以处理drawScene:
调用。
这是cocos2d代码的相关片段。在显示链接线程上调用MyDisplayLinkCallback
。
static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
{
CVReturn result = [(CCDirectorDisplayLink*)displayLinkContext getFrameForTime:outputTime];
return result;
}
- (CVReturn) getFrameForTime:(const CVTimeStamp*)outputTime
{
#if (CC_DIRECTOR_MAC_THREAD == CC_MAC_USE_DISPLAY_LINK_THREAD)
...
#else
// Display link thread blocks here:
[self performSelector:@selector(drawScene) onThread:_runningThread withObject:nil waitUntilDone:YES];
#endif
return kCVReturnSuccess;
}
当主线程尝试运行CVDisplayLinkStop()
阻止直到显示链接线程中的显示链接回调结束时,会出现问题。由于回调是在等待主线程处理其drawScene:call的同时,两个线程都变为死锁。
- (void) stopAnimation
{
...
if( displayLink ) {
// Main thread blocks here:
CVDisplayLinkStop(displayLink);
...
}
所以,现在我的解决方法。我添加了一行来运行主线程的runloop,以强制执行drawScene:
调用,从而解除对显示链接线程的阻塞。这样,当你致电CVDisplayLinkStop()
时,你就是安全的。这是我的补充(cocos2d 2.1版本中的CCDirectorMac.m第473行):
- (void) stopAnimation
{
...
if( displayLink ) {
#if (CC_DIRECTOR_MAC_THREAD != CC_MAC_USE_DISPLAY_LINK_THREAD)
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
#endif
CVDisplayLinkStop(displayLink);
...
}
我不确定这是 正确的事情,可能有更好的方法来解决这个问题,但目前这种解决方法对我来说还不错。
答案 1 :(得分:0)
感谢这篇文章,它帮助我弄清楚了如何通过在单独线程(而不是主线程)上处理显示链接回调,在非cocos2d应用程序中解决相同的死锁。
{{1}}