简体   繁体   中英

Concurrency with core data

I am using multi-threading to get data, parse it, create objects and store them. And after this is all done, I want the window to be shown. But now I have 2 issues:

  • I have a deadlock
  • My barrier does not act as a barrier.

I think the deadlock is because I am updating the managedObjectContext in several threads at once.

  1. So I changed my managedObjectContext with the ConcurrencyType:

     __managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
  2. And created an importContext for the concurrency queue and assigned the parentContext:

     NSManagedObjectContext *importContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; importContext.parentContext = self.managedObjectContext; 
  3. And put my operations in a performBlock for the importContext:

     [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]; }); }); }]; 

Approach 1: In each method, I select a subset of object, delete these and then create new objects and save this. (I thought the delete was quicker than doing a fetch and check for the existence for every object to be created). So: In Method AI select all AObjects, delete them and create new AObjects. In Method BI select all BObjects, delete them and create new BObjects. In Method CI select all CObjects, delete them and create new CObjects.

But then I get an error "An NSManagedObjectContext cannot delete objects in other contexts".

So approach 2: I removed the delete. But now I get various different errors..... And the barrier does not wait for the other threads to be executed.

Q1: What am I doing wrong?

Q2: how do I get the barrier to wait for the 3 threads to be completed

Q3: how can I delete / purge objects on various threads?

(I have read the Apple release notes and doc's, but I can't find this a clear explanation on the combination for multithreading and managedContext.)

You cannot call dispatch_async within performBlock . A managed object context of type NSPrivateQueueConcurrencyType has it's own dispatch queue for executing the operations.

You try to do several operations in parallel by moving them to a different dispatch queue, but that is not possible.

If you really have to do multiple operations in parallel, you must create a private concurrency type MOC for each operation.

ADDED:

There are several ways to wait for all operations to complete:

  • You could increment a counter at the end of each performBlock: and check if it's value is (in your example) 3.
  • You could create a semaphore ( dispatch_semaphore_create ) for each operation with initial value zero, wait for all the semaphores ( dispatch_semaphore_wait ) and signal the semaphore at the end of each performBlock .
  • And I am sure that there are better/more elegant/more sophisticated ways to do this.

BUT: As I re-read your question, I see that you try to delay the

[self.window makeKeyAndVisible];

until all Core Data fetch operations have completed. This is not a good design, because the user will see nothing until your data import is done.

A better design is to show an initial view immediately, and update that view when the background operations have fetched data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM