核心数据多线程提取记录 [英] Core data multithreading fetch record

查看:169
本文介绍了核心数据多线程提取记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个怀疑核心数据中的多线程。如果我们使用多线程,我们应该使用单独的NSManagedObjectContext插入新数据或更新,否则我们可以使用父子上下文方法。但我只创建新的NSManagedObjectContext。我的问题是,我应该使用单独的NSManagedObjectContext甚至获取在后台线程也。

I have one doubt about multithreading in coredata. if we are using multithreading we should use separate NSManagedObjectContext for inserting new data or updating or else we can use parent child context method. But i am creating new NSManagedObjectContext only. My question is that should i use separate NSManagedObjectContext for even fetching in background thread also. If not (i.e. we can use main queue NSManagedObjectContext only) than why i m getting __psynch_mutexwait error.

非常感谢,

推荐答案

首先,Core Data是线程安全的。但是,您必须遵循以下规则:

First, Core Data is thread safe. However you must follow the rules:


  1. NSManagedObjectContext 您只能在分配给它的线程上使用它。 -init 导致一个上下文被分配给它被创建的线程。 -initWithConcurrencyType:将允许您创建与其他线程/队列相关联的上下文。

  2. 任何 NSManagedObject 相关联的NSManagedObjectContext 绑定到与它来自的上下文相同的线程/队列

  3. 没有第三条规则

  1. NSManagedObjectContext is thread bound. You can only use it on the thread it is assigned to. -init causes a context to be assigned to the thread it is created on. Using -initWithConcurrencyType: will allow you to create contexts associated to other threads/queues.
  2. Any NSManagedObject associated with a NSManagedObjectContext is tied to the same thread/queue as the context it came from
  3. There is no third rule

您可以在线程之间传递 NSManagedObjectID 实例,但是规则1和2必须遵守。从您的描述中我相信您违反了这些规则。

You can pass NSManagedObjectID instances between threads but rules 1 and 2 must be obeyed. From your description I believe you are violating these rules.



我个人不推荐使用NSManagedObjectID。有更好的解决方案。 - Marcus S. Zarra

Personally I do not recommend using NSManagedObjectID either. There are better solutions. – Marcus S. Zarra

Marcus,这是Core Data的线程最简洁的解释。从使用它,因为它的介绍,有几天我仍然得到这些规则错误!你提到更好的解决方案 - 你能详细说明吗?

Marcus, this is the most succinct explanation of Core Data's threading I've read. Having used it since it's introduction, there are days I still get these rules wrong! You mention "better solutions" — can you elaborate?

我有一个相当强烈的不信任的使用 NSManagedObjectID 。在许多情况下,它不会从一个应用程序生命周期保持不变。最初,基于文档,我们(Cocoa开发人员)认为这是我们为我们生成的神话主键。这已经证明是不正确的。

I have a fairly strong distrust of the use of the NSManagedObjectID. It does not stay the same from one application lifecycle to another in many situations. Originally, based on the documentation, we (Cocoa developers in general) believed it was our mythical primary key being generated for us. That has turned out to be incorrect.

在有父/子上下文的现代开发中,景观更令人困惑,还有一些有趣的陷阱,我们需要注意。鉴于当前的景观,我不喜欢它比我以前。那么我们使用什么?

In modern development with parent/child contexts the landscape is even more confusing and there are some interesting traps that we need to watch out for. Given the current landscape I dislike it more than I did previously. So what do we use?

我们应该生成自己的。它不需要太多。如果您的数据没有来自服务器的主键(很常见,从基于Ruby的服务器有一个 id ),然后创建一个。我喜欢叫它 guid ,然后有一个类似于

We should generate our own. It doesn't need to be much. If your data does not have a primary key from the server already (pretty common to have an id from a Ruby based server) then create one. I like to call it guid and then have an -awakeFromInsert similar to this:

- (void)awakeFromInsert
{
  [super awakeFromInsert];
  if (![self primitiveValueForKey:@"guid"]) {
    [self setPrimitiveValue:[[NSProcessInfo processInfo] globallyUniqueString] forKey:@"guid"];
  }
}

注意:此代码

您检查该值,因为 -awakeFromInsert 每次调用一次上下文。然后我通常会在我的 NSManagedObject 实例上有一个方便的方法类似于:

You check the value because -awakeFromInsert is called once per context. Then I will generally have a convenience method on my NSManagedObject instances similar to:

@implementation MyManagedObject

+ (MyManagedObject*)managedObjectForGUID:(NSString*)guid inManagedObjectContext:(NSManagedObjectContext*)context withError:(NSError**)error
{
  NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:[self entityName]];
  [fetch setPredicate:[NSPredicate predicateWithFormat:@"guid == %@", guid]];

  NSArray *results = [context executeFetchRequest:request error:error];
  if (!results) return nil;

  return [results lastObject];
}

@end

/ strong>这段代码是在网络浏览器中编写的,可能无法编译。

NOTE: This code is written in the web browser and may not compile.

这会让错误处理和上下文/线程控制到开发人员,检索当前上下文中的对象,并让我们将对象从一个上下文反弹到另一个上下文。

This leaves error handling and context/threading control up to the developer but provides a convenience method to retrieve an object on the current context and lets us "bounce" an object from one context to another.

这比 objectWithID: ,并且应该仔细使用,并且只有在你需要将一个对象从一个上下文弹出到另一个上下文保存向上移动它堆栈的情况下。

This is slower than -objectWithID: and should be used carefully and only in situations where you need to bounce an object from one context to another after a save moves it up the stack.

和我做的大多数事情一样; 这不是通用解决方案。这是一个基准,应该根据每个项目进行调整。

As with most things I do; this is not a generic solution. It is a baseline that should get adjusted on a per project basis.

这篇关于核心数据多线程提取记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆