【问题标题】:Dispatch call to main queue inside UIBackgroundTaskIdentifier调度调用到 UIBackgroundTaskIdentifier 内的主队列
【发布时间】:2014-02-26 06:01:28
【问题描述】:

我正在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. 这是一个好的设计吗?

【问题讨论】:

  • 感谢 Rob 指出这一点。我已经编辑了问题。

标签: objective-c objective-c-blocks grand-central-dispatch uibackgroundtask


【解决方案1】:

在回答您的问题时,那些已分派到主队列的块按您预期的方式运行,并且一切正常,当应用程序重新回到前台时,您会看到 UI 已正确更新。两个警告:

  1. 您需要确保在最终调度完成之前不调用endBackgroundTask。您可以通过以下任一方式实现:

    • 使最终的 UI 调度同步;或

    • 将endBackgroundTask 作为您分派到主队列的最后一个块中的最后一项。

    但是endBackgroundTask 的时机很重要,您要确保在将后台任务标记为已完成并指示它可能已暂停之前更新您的 UI。

  2. 我不知道你想如何处理无法完成后台任务,但通常你也会在过期处理程序中调用endBackgroundTask,否则应用程序将在后台被终止任务没有在规定的时间内完成。有关示例,请参阅 iOS 应用程序编程指南 的 App 状态和多任务处理 章节的 Executing a Finite-Length Task in the Background。

【讨论】:

  • 与其同步调度,不如调用endBackgroundTask在最后一个块调度到主线程。
  • @newacct 这也有效。我个人更喜欢我的方法的对称性(在创建它的同一线程上结束任务;只将需要主队列的东西分派到主队列;等等),但我也理解你的方法的吸引力,所以我'已经修改了我的答案以包含该选项(实际上,当我第一次起草答案时,我已经有了它,但我认为我在那里抛出了太多选项;哈哈)。
猜你喜欢
  • 1970-01-01
  • 2018-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-26
  • 1970-01-01
  • 1970-01-01
  • 2018-03-15
相关资源
最近更新 更多