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