0

我正在使用多线程来获取数据、解析数据、创建对象并存储它们。完成这一切后,我希望显示窗口。但现在我有两个问题:

  • 我有一个僵局
  • 我的屏障不充当屏障。

我认为死锁是因为我一次在多个线程中更新 managedObjectContext。

  1. 所以我用 ConcurrencyType 改变了我的 managedObjectContext:

    __managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    
  2. 并为并发队列创建了一个 importContext 并分配了 parentContext:

    NSManagedObjectContext *importContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    importContext.parentContext = self.managedObjectContext;
    
  3. 并将我的操作放在 importContext 的 performBlock 中:

    [importContext performBlock:^{
    
      dispatch_async(backgroundQueue, ^{
      [myObject methodAWithContext:importContext];
      });
    
      dispatch_async(backgroundQueue, ^{
      [myObject methodBWithContext:importContext];
      });
    
      dispatch_async(backgroundQueue, ^{
      [myObject methodCWithContext:importContext];
      });
    
    
      dispatch_barrier_async(backgroundQueueM, ^{
      // create barrier to wait for the first 3 threads to be completed.
       dispatch_async(dispatch_get_main_queue(), ^{
    
        // Save the data from the importContext tot the main context on the main queue
        NSError *importError = nil;
        [importContext save:&importError];
        [importContext.parentContext performBlock:^{
           NSError *parentError = nil;
           [importContext.parentContext save:&parentError];
        }];
    
       [self.window makeKeyAndVisible];
    
       });
      });
    }];
    

方法 1:在每种方法中,我选择对象的一个​​子集,删除它们,然后创建新对象并保存它。(我认为删除比获取并检查要创建的每个对象的存在更快)。所以:在 M​​ethod AI 中选择所有 AObjects,删除它们并创建新的 AObjects。在 Method BI 中选择所有 BObjects,删除它们并创建新的 BObjects。在 Method CI 中选择所有 CObjects,删除它们并创建新的 CObjects。

但随后我收到错误消息“NSManagedObjectContext 无法删除其他上下文中的对象”。

所以方法2:我删除了删除。但是现在我得到了各种不同的错误.....并且屏障不等待其他线程被执行。

Q1:我做错了什么?

Q2:如何获得等待3个线程完成的屏障

Q3:如何删除/清除各个线程上的对象?

(我已经阅读了 Apple 发行说明和文档,但我找不到关于多线程和 managedContext 组合的清晰解释。)

4

1 回答 1

3

你不能dispatch_async在 内打电话performBlock。类型的托管对象上下文NSPrivateQueueConcurrencyType有它自己的调度队列来执行操作。

您尝试通过将它们移动到不同的调度队列来并行执行多个操作,但这是不可能的。

如果确实要并行执行多个操作,则必须为每个操作创建一个私有并发类型 MOC。

添加:

有几种方法可以等待所有操作完成:

  • 您可以在每个末尾增加一个计数器performBlock:并检查它的值是否为(在您的示例中)3。
  • 您可以为每个初始值为零的操作创建一个信号量 ( dispatch_semaphore_create),等待所有信号量 ( dispatch_semaphore_wait) 并在每个信号量的末尾发出信号量performBlock
  • 而且我确信有更好/更优雅/更复杂的方法来做到这一点。

但是:当我重新阅读您的问题时,我看到您试图推迟

[self.window makeKeyAndVisible];

直到所有核心数据获取操作都完成。这不是一个好的设计,因为在您的数据导入完成之前,用户什么都看不到。

更好的设计是立即显示初始视图,并在后台操作获取数据时更新该视图。

于 2012-08-18T10:59:27.423 回答