调度调用到 UIBackgroundTaskIdentifier 内的主队列

Posted

技术标签:

【中文标题】调度调用到 UIBackgroundTaskIdentifier 内的主队列【英文标题】:Dispatch call to main queue inside 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];        
    );

所以我有两个问题。

    如果我的应用程序在某些处理过程中进入后台,对主队列的 dispatch_async 调用会发生什么情况? 这是一个好的设计吗?

【问题讨论】:

感谢 Rob 指出这一点。我已经编辑了问题。 【参考方案1】:

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

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

    使最终的 UI 调度同步;或

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

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

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

【讨论】:

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

以上是关于调度调用到 UIBackgroundTaskIdentifier 内的主队列的主要内容,如果未能解决你的问题,请参考以下文章

如何将始终从特定线程调用其回调的侦听器包装到符合 subscribeOn 定义的调度程序的 Observable 中?

在无状态 Node.js 应用程序中调度函数调用

调度传入 RPC 调用时出现异常

无法从 GCP 调度程序调用 Google Cloud Function

如何以编程方式为 Kendo Ui 调度程序调用导航事件

Contiki-一个进程的例子