Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data: parent context blocks child

I'm doing some background processing in an app with core data. The background processing is done on a child managedObjectContext. Context initialization:

appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

// the moc in appDelegate is created with .MainQueueConcurrencyType
mainThreadMOC = appDelegate.managedObjectContext!
backgroundMOC = NSManagedObjectContext(concurrencyType:NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
backgroundMOC?.parentContext = mainThreadMOC

Background processing is done in the following method:

// download all new transaction log entries
func syncItems() {

... set up the query object for parse

let moc = CoreDataStore.sharedInstance.backgroundMOC

// perform download
moc?.performBlock( {
    self.runQuery(query)   // Download stuff und do some core data work
    })
}

The debugger shows that all work inside the block is indeed in a background thread.

When I call this function from the main thread and immediately block the main thread (for test purpose) with a lengthy core data operation, I see that the background thread stops and only continues execution when the main thread is idle.

// this is called from a view controller in the main thread

syncItems() // should start to work in background
for i in 0...200 {
    // do some core data work in main thread
}
// syncItems starts to work after the blocking for-loop ends.

Why is that happening?

like image 788
tzer Avatar asked Apr 27 '15 15:04

tzer


1 Answers

Don’t use a parent-child context setup.

Parent-child context are not a good approach for just about anything. Just use a simple stack: two contexts with one shared persistent store coordinator.

Parent-child contexts just add a lot of confusion without giving you much of anything. It’s a pretty misunderstood concept. I wish people like mzarra would f***ing stop advocating that setup. It’s a disservice to the community.

If your background context is a child context of your main context, you will have to lock both the main and the background context, whenever the background context needs to save. This blocks the UI. And you’ll have to lock the UI a 2nd time to propagate those changes from the UI into the PSC. If you use a background context, you will have to merge changes into the main context, but you'll only do work for those objects that are currently registered with that context. If you added new objects, or updated / deleted objects that are not currently registered (referenced) that’s basically a no-op.

like image 116
Daniel Eggert Avatar answered Sep 30 '22 10:09

Daniel Eggert