2012-10-05 58 views
1

我有一個GCD圖隊列更新我的OpenGL ES場景,其被構造是這樣的:如何拆卸GCD隊列?

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

當應用程序辭職活性或進入背景(兩者)我停止的OpenGL由CADisplayLink無效描繪運行的循環。

但問題是,dispatch_asyn調度繪圖塊,直到CADisplayLink失效後。當用戶按下主頁按鈕時,我的應用程序崩潰,因爲它嘗試在OpenGL中繪製框架,即使iOS已經在上下文中進行了撕碎。

有沒有辦法殺死/暫停GCD隊列,以便它不再發送任何東西?

+0

'dispatch_suspend'將阻止另外從排隊開始工作,但不做任何與當前正在運行的作業。 (我不知道這兩種情況哪一個適用於此) – Rob

+0

除了Simon的建議之外,我可能會指出你的'dispatch_semaphore_wait()'在錯誤的地方。它需要在'dispatch_async()'之前,而不是在你的異步塊中。像這樣使用信號量的全部原因是爲了防止一次在GCD隊列中添加多個渲染塊,並且在應用程序轉到背景後看到渲染框架的原因是因爲一堆他們堆積在你的隊列中。我敢打賭,在您將等待移至異步調度之前,您會發現這種崩潰會消失。 –

回答

2

我認爲最簡單的方法是在執行塊之前檢查應用程序中的標誌。例如:

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

可以在applicationDidEnterBackgroundapplicationWillTerminate設置您的應用程序委託這些值。

你也可以試試這個:

dispatch_suspend(drawingQueue); 
dispatch_release(drawingQueue); 

不太清楚那些雖然。

這裏的一切細節:https://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html

+1

'dispatch_release'只會減少隊列的保留計數,一旦保留計數達到零,就可以將其解除分配,所以這不可能幫助iFrog。 'dispatch_suspend'更有希望,但是取決於塊是否已經運行。 (如果還沒有運行,上面的解決方案可能更簡單。) – Rob

+0

謝謝! Upvote需要15點聲望。會做到這一點:-) –

+0

你應該能夠現在! :) –