5

我正在運行UIBackgroundTaskIdentifier下的某個任務,因爲我想在後臺運行它。我的代碼看起來像這樣。調用UIBackgroundTaskIdentifier中的主隊列

-(void) function 
{ 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 

     UIBackgroundTaskIdentifier BGIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{}];  

     // some processing 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      // some UI stuff 
     }); 

     // some processing again 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      // some UI stuff again 
     }); 

     [[UIApplication sharedApplication] endBackgroundTask:BGIdentifier];   
    }); 
} 

所以我有兩個問題。

  1. 如果我的應用程序在後臺進行某些處理時發生dispatch_async調用主隊列會發生什麼情況?
  2. 這是一個很好的設計?
+0

感謝Rob指出了這一點。我編輯了這個問題。 – shshnk

回答

2

在回答你的問題,那些派遣塊到主隊列操作如你所期望,一切都將正常工作,而當應用程序被帶回到前臺,你會看到更新的用戶界面正常。兩個警告:

  1. 你會想,以確保最終的調度完成之前endBackgroundTask不會被調用。您可以通過以下方式實現此目的:

    • 使最終的UI調度同步;或

    • endBackgroundTask作爲最後一個分派給主隊列的最後一個項目。

    但這endBackgroundTask的時機很重要,你要確保你標記你的後臺任務已完成,並表明它可能被暫停之前,您更新UI。

  2. 我不知道如何處理失敗以完成後臺任務,但通常您也可以在過期處理程序中調用endBackgroundTask,因爲否則應用程序將立即終止,如果後臺任務未完成,在規定的時間內完成。舉例來說,請參閱iOS應用程序編程指南應用程序狀態和多任務章節的Executing a Finite-Length Task in the Background

+0

而不是同步調度,他應該在派發到主線程的那些塊的最後一個塊中調用'endBackgroundTask'。 – newacct

+0

@newacct也適用。我個人比較喜歡我的方法的對稱性(在創建它的同一個線程上結束任務;僅向需要主隊列的主隊列發送內容;等等),但我也理解你的方法的吸引力,所以我我已經修改了我的答案,以包含該選項(當我第一次起草答案時,我確實已經在那裏了,但是我認爲我在那裏扔了太多選項;哈哈)。 – Rob