Re: Core Data & threads [re: Ping: Look for hints for "nested transaction" problem with Core Data]
Re: Core Data & threads [re: Ping: Look for hints for "nested transaction" problem with Core Data]
- Subject: Re: Core Data & threads [re: Ping: Look for hints for "nested transaction" problem with Core Data]
- From: Ben Trumbull <email@hidden>
- Date: Fri, 16 Mar 2007 02:04:07 -0700
Can I summarize with "if I use several thread, I should use one
NSManagedObjectContext per thread" ?
At least one, yes.
But in this case, how can I set a background thread to regularly
save the context ?
What problem are you actually trying to solve ?
You can easily start fighting the transactional scope, isolation, and
other features NSManagedObjectContexts are trying to provide.
Things get weird from a UI perspective if other threads save changes
out from underneath the user in a document based application. For
example, Auto-save goes to a different file so it's not conflicting
with the user's intention.
Also, undo management with multiple threads is an intractable UI problem.
To regularly do things, an NSTimer or -performSelector...afterDelay:0 works.
A large import operation works with multiple threads importing
different pieces of the data quite naturally.
Are you having performance problems with a vanilla save ?
If you are using multiple NSManagedObjectContexts, as with multiple
threads, then you'll have to mirror the changes across the contexts
so the other context can save them.
The NSManagedObjectContextObjectsDidChangeNotification is issued at
the end of every event (or sooner) and contains a userInfo dictionary
about everything that changed in the event. You can have an object
listen for it, and (in the original thread) package up the change
details as basic immutable value objects (objectIDs, strings, etc).
Or you can build up the change details by polling the context's
inserted, updated, deleted sets.
Then you can have it pass off the change details to the other thread,
which at its leisure, can receive the changes and integrate them into
its context.
I've actually seen this done across a local network with DO, fwiw.
Most impressive Core Data application from WWDC 2004. Actually, all
of 2004 ...
The main alternative to mirroring the changes is to use the Command
design pattern to have the background thread compute the necessary
changes independently. This is how seriously large scale distributed
systems approach it.
All these complications are a hint that the idiom of having one
thread save pending changes from another thread's context is not well
supported or encouraged.
The typical pattern is inverted from what you're trying to do. One
context saves changes and informs other contexts about the new
changes using the NSManagedObjectContextDidSaveNotification.
Moreover I did not understand which mechanism will prevent these
managedObjectContexts to clash when accessing the same persistent
store.
Core Data will manage that for you. MOCs know how to lock their
coordinators, and the coordinators know how to use SQLite's file
locking.
You just need to decide on a merge policy for resolving conflicts if
multiple threads try to update the same row.
The default policy is for -save: to return an error with a userInfo
that has information about the conflicts that you can use to
customize a recovery. Core Data also provides 4 merge policies like
"last writer wins" and "merge by property".
Ask wikipedia about "optimistic locking".
For most apps, it's usually cheaper to recover from a conflict than
prevent any possible conflict. If your contexts share a coordinator,
you can manually adjust the scope of locking by locking and unlocking
the coordinator directly.
--
-Ben
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden