iphone - 我应该使用NSOperationQueue和NSOperation而不是NSThread吗?

时间:2012-09-05 14:30:08

标签: iphone objective-c nsthread nsoperation nsoperationqueue

我正面临着我的应用程序的设计问题。


基本上,以下是我在我的应用程序中要做的事情。

单个任务是这样的:

  1. 从基础CoreData数据库
  2. 中读取自定义对象
  3. 从网址
  4. 下载json
  5. 解析json以更新自定义对象或创建一个新对象(解析可能需要1 - 3秒,大数据)
  6. 分析自定义对象(将涉及一些计算,可能需要1到5秒)
  7. 将自定义对象保存到CoreData数据库中。
  8. 可能会同时执行许多任务。

    一项任务中的步骤显然是ordered(即,没有第2步下载json,第3步无法继续),但它们也可以是discrete。我的意思是,例如,task2的第4步可以在task1的第3步之前执行(如果task2的下载速度比task1的速度快)

    任务有优先权。用户可以启动具有更高优先级的任务,因此将尝试在所有其他任务之前执行所有任务的步骤。


    我希望UI能够尽可能地响应。

    所以我打算创建一个优先级最低的NSThread。

    我在该线程中放置了一个自定义优先级事件队列。任务的每一步都成为一个事件(工作单位)。因此,例如,下载json的步骤1成为事件。下载后,该事件会为步骤3生成另一个事件并将其放入队列中。每个事件都有自己的优先级设置。


    现在我看到这篇文章:Concurrency and Application Design。 Apple建议我们Move Away from Threads并使用GCDNSOperation

    我发现NSOperation非常符合我的草稿设计。但我有以下问题:

    • 考虑到iPhone / iPad cpu核心,我应该只使用一个NSOperationQueue还是创建多个?
    • NSOperationQueue或NSOperation是否以最低线程优先级执行?执行是否会影响UI响应(我关心因为步骤涉及计算)?
    • 我可以从另一个生成NSOpeartion并将其放入队列吗?我在NSOperation中没有看到队列属性,我怎么知道队列?
    • 如何将NSOperationQueue与CoreData合作?每次访问CoreData时,我应该创建一个新的上下文吗?那会贵吗?
    • 任务的每一步都变为NSOperation,这个设计是否正确?

    由于

5 个答案:

答案 0 :(得分:4)

  

考虑到iPhone / iPad cpu核心,我应该只使用一个NSOperationQueue还是创建多个?

两个(CPU,网络+ I / O)或三个(CPU,网络,I / O)串行队列应该适用于大多数情况,以保持应用程序响应和您的程序流工作他们必须遵守的是什么。当然,您可能会发现另一种组合/配方适用于您的特定工作分配。

  

NSOperationQueue或NSOperation是否以最低线程优先级执行?执行是否会影响UI响应(我关心因为步骤涉及计算)?

默认不是。如果您想降低优先级,请参阅-[NSOperation setThreadPriority:]

  

我可以从另一个生成NSOpeartion并将其放入队列吗?我在NSOperation中没有看到队列属性,我怎么知道队列?

不确定。如果您使用我概述的串行方法,找到正确的队列很容易 - 或者您可以使用ivar。

  

如何将NSOperationQueue与CoreData合作?每次访问CoreData时,我应该创建一个新的上下文吗?那会贵吗?

(无评论)

  

任务的每一步都变为NSOperation,这个设计是否正确?

是的 - 将您的队列划分为它所绑定的资源是一个好主意。

答案 1 :(得分:0)

  • 从外观上看,NSOperationQueue就是你所追求的。您可以设置要同时运行的并发操作数。如果使用多个NSOperation,它们将同时运行...除非您自己处理队列,这与使用NSOperationQueue相同

  • 线程优先级......我不确定你的意思,但在iOS中,UI绘图,事件和用户交互都在主线程上运行。如果你在后台线程上运行东西,无论你运行的操作有多复杂或繁重,接口仍然会响应

  • 生成和处理你应该在主线程上执行的操作,因为它不需要任何时间,你只需在后台线程中运行它们,这样你的主线程就不会被锁定

  • CoreData,我没有特别使用它,但到目前为止,每个Core~我使用它在后台线程上都能很好地工作,所以它应该不是问题

  • 就设计而言,这只是一个观点......对于我来说,每个任务都有一个NSOperation,并让它处理所有步骤。如果您想提供一些反馈或继续进行其他下载或某事,可以在步骤完成时编写回调

答案 2 :(得分:0)

当多线程不会因为使用NSThread而不是NSOperation而不同时,计算的影响。但请记住,当前的iOS设备必须使用双核处理器。

您遇到的一些问题不是很具体。您可能想要也可能不想使用多个NSOperationQueue。这一切都取决于你想要如何接近它。如果您有不同的NSOperation子类或不同的NSBlockOperations,则可以使用优先级管理执行顺序,或者您可能希望为不同类型的操作(尤其是在使用串行队列时)使用不同的队列。我个人更喜欢在处理相同类型的操作时使用1个操作队列,并且当操作不相关/可靠时具有不同的操作队列。这使我可以灵活地根据发生的事情取消和停止队列中的操作(网络丢弃,应用程序转到后台)。

我从未找到基于执行当前操作期间发生的事情添加操作的充分理由。如果您需要这样做,您可以使用NSOperationQueue的类方法currentQueue,它将为您提供当前操作正在运行的操作队列。

如果您使用NSOperation进行核心数据工作,我建议为每个特定操作创建一个上下文。确保初始化main方法中的上下文,因为这是您在NSOperation后台执行的正确线程上的位置。

每个任务不一定需要一个NSOperation对象。您可以下载数据并在NSOperation中解析它。您还可以抽象地进行数据下载,并使用NSOperation的完成块属性对下载的内容进行数据处理。这将允许您使用相同的对象来获取数据,但具有不同的数据操作。

我的建议是阅读NSOperation,NSBlockOperation和NSOperationQueue的文档。检查当前的设计,了解如何使用当前项目调整这些类。我强烈建议你去NSOperation家族而不是NSThread家庭。

祝你好运。

答案 3 :(得分:0)

只是添加到@ justin的回答

  

如何将NSOperationQueue与CoreData合作?每次我访问   CoreData,我应该创建一个新的上下文吗?那会贵吗?

NSOperation与核心数据结合使用时,您应该非常小心 你总是必须记住的是,如果你想在一个单独的线程上运行CoreData操作,你必须为该线程创建一个新的NSManagedObjectContext,并共享主要的托管对象上下文持久性商店协调员(“主要”MOC是应用代表中的一个)。

此外,非常重要该线程的新托管对象上下文是从该线程创建 。 因此,如果您计划将核心数据与NSOperation一起使用,请确保使用NSOperation的main方法而不是init初始化新的MOC。

Here是关于核心数据和线程的非常好的文章

答案 4 :(得分:-1)

使用GCD - 它比NS *更好的框架

将所有CoreData访问权保留在一个队列中,并在例程结束时将dispatch_async保存到CoreData数据库。

如果您有开发者帐户,请查看此WWDC视频:https://developer.apple.com/videos/wwdc/2012/?id=712