【问题标题】:Can I use MOC's performBlock: inside an NSOperation subclass?我可以在 NSOperation 子类中使用 MOC 的 performBlock: 吗?
【发布时间】:2018-06-29 12:12:32
【问题描述】:

文档声明带有 NSPrivateQueueConcurrencyType 的 NSManagedObjectContext 允许用户通过使用 performBlock: 来执行异步代码。但是,如果我想编写一个 NSOperation 子类来处理此类子上下文/私有队列设置中的托管对象,会发生什么?

例如:

// Get managed object IDs from selected objects (defined in one of my own categories).
NSArray * selectedObjIDs = [NSManagedObjectContext IDsWithObjects:self.arrayController.selectedObjects];

NSBlockOperation * operation = [NSBlockOperation blockOperationWithBlock:^
{
    NSManagedObjectContext * childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    childContext.parentContext = myMainMOC;

    [childContext performBlock:^
     {
         // Get objects in child context with previously generated managed object IDs (again, from my own category).
         NSArray * privateObjects = [childContext objectsWithIDs:selectedObjIDs];

         // Do something with the objects.
         for( NSManagedObject * object in privateObjects )
         {
             [object setValue:@"New Title" forKey:@"title"];
         }

         [childContext save:NULL];
     }];
}];

// Execute in our own private NSOperationQueue.
[self.backgroundQueue addOperation:operation];

代码运行良好,但在两个块内设置断点时,我可以看到执行首先进入后台线程 A(由 NSBlockOperation 生成),然后进入后台线程 B(专用于子 MOC - 正如预期的那样。

(顺便说一句:我相信我在 Apple 的 WWDC 会话“高级 NSOperations”的示例代码中看到了等效设置。)

问题 #1:这两个嵌套调度是否存在某种问题,即在性能方面?这对我来说似乎不对 - 代码不应该只在子 MOC 的私有队列中运行吗?

问题 #2:假设我将 NSOperation 子类化(而不是使用 NSBlockOperation)。我是否应该重写它的“异步”属性以向真的返回 YES,只使用子 MOC 的私有队列?

【问题讨论】:

  • 不确定我是否关注。如果您看到代码在后台线程“B”上运行,那么私有队列有什么问题? “B”在某种程度上是错误的吗?
  • 是的,这是我的问题 #1(可能不清楚):主要威胁上的代码生成线程 A 然后生成线程 B 是否存在问题?这就是我所说的“嵌套调度”的意思。

标签: ios multithreading macos core-data concurrency


【解决方案1】:

您的代码并没有完全错误,但它比需要的更复杂。

当您调用performBlock 时,您是在告诉托管对象上下文在私有队列上异步执行该块。对于调用performBlock 的代码,该块已经是异步的。将其包裹在 NSOperation 中可能是安全的,但也完全没有必要。由于performBlock 的异步特性,只要您的代码调用performBlockNSOperation 就会完成。总之,NSOperation 在这里是完全没有必要的。

您可以将performBlock 替换为performBlockAndWait,但这没有多大意义。你会强迫NSOperation 等待,但没有充分的理由。

您提到的子类化NSOperation 也是不必要的,除非您有一些其他未提及的异步要求。如何配置NSOperation 无关紧要——去掉它即可。

更新,因为在评论中您似乎确实有其他异步要求...

  • 代码可能是安全的,具体取决于您的其他操作。
  • 由于performBlock 立即返回,队列中的下一个操作将在不同队列上与此操作并行运行。这有关系吗?这取决于队列中的其他操作在做什么。如果他们依赖这个performBlock 已经完成,那就是个问题。您可以使用performBlockAndWait 处理此问题,以保持队列连续。

【讨论】:

  • 感谢 Tom,但我真的很想使用 NSOperation。我的代码很大程度上依赖于它的强大特性,比如依赖项。此外,在 NSOperation 中使用私有子 MOC 进行处理显然是有意的,并且在包括 Apple WWDC 会话在内的各种来源中都建议使用它。我的问题是这两个“嵌套”调度是否在某种程度上不好。我知道 performBlockAndWait: 但它也感觉不对 - 正如你所说。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-05
  • 2014-11-23
  • 1970-01-01
相关资源
最近更新 更多