1

NSWindowテスト目的で「cocos Player」を起動するコンテンツ エディタを構築しています。ユーザーは、一部のコンテンツをテストしてから、ウィンドウを閉じることができます。

そのため、cocos をシャットダウンして、同じアプリ内で再起動できるようにする必要があります。

CC_MAC_USE_DISPLAY_LINK_THREADスレッド モデルを使用すると、すべてが機能します。これを機能させるには、修正を加える必要がありましたCCDirectorMac。を使用するときにandによって nil に設定されていないため、 toCCDirectorMac | stopAnimationを設定する必要がありました。_runningThreadnil#if#elifCC_MAC_USE_DISPLAY_LINK_THREAD

とにかく、ディレクターを「終了」して、後で問題なく再起動できるようになりました。

私の質問は次のとおりです。cocos2D をときどき使用する AppKit エディターを構築している場合CC_MAC_USE_MAIN_THREAD、ドキュメントで提案されているスレッド モデルは実際にはどのようなものでしょうか?

私が使用するCC_MAC_USE_MAIN_THREADと、次の行にハングインします。stopAnimation

CVDisplayLinkStop(displayLink);

メインスレッドは問題なく、ツールのスレッド化の問題を回避できると思います。パフォーマンスは問題ではありません。cocos2d をシャットダウンして再起動するサンプル コードを見つけることができませんNSWindow

シャットダウン/再起動する私の手順は次のとおりです。

  1. 電話[[CCDirector sharedDirector] end]
  2. これはstopAnimation
  3. 次に、最初に行ったのと同じ方法で cocos2d を再初期化します

Mac デスクトップ アプリのスレッド モデルに関するアドバイスと、CVDisplayLinkStopハングする理由を教えてください。

前もって感謝します。

4

2 に答える 2

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: 呼び出しを処理するのを待っているため、両方のスレッドがデッドロック状態になります。

- (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);
    ...
}

これが正しいことかどうかはわかりません。おそらくこれに対処するためのより良い方法がありますが、現時点ではこの回避策で十分です。

于 2013-08-03T03:34:09.787 に答える