Re: Core Data: Progress bar using Sheet, modifying context in thread
Re: Core Data: Progress bar using Sheet, modifying context in thread
- Subject: Re: Core Data: Progress bar using Sheet, modifying context in thread
- From: Jakob Olesen <email@hidden>
- Date: Fri, 4 Aug 2006 11:45:10 +0200
On 04/08/2006, at 6.05, Bill Coleman wrote:
Question 1: I'd like the import or export process to be document-
modal, with the progress of the operation displayed in a sheet.
This is a little tricky, since once you call beginSheet:
modalForWindow: ..., you can't do any more processing. So, to
perform the actual operation, I first start an NSThread. Getting it
to quit properly was tricky, as you have to use
performSelectorOnMainThread: to get the endSheet: call to work.
My question is -- is this the right way to do this? Is there a
better way? It seems to be fraught with problems.
You should try to avoid using a thread for something like this. Most
classes in AppKit are not thread safe, so you should only touch them
in the main thread. This goes for NSManagedObjectContext and
NSManagedObject as well.
Read the Core Data documentation on multithreading, but really, try
to avoid threads.
Question 2: Export seems to work ok. Import, however, acts a bit
funny. I create new rows for import by calling [NSEntityDescription
insertNewObjectForEntityForName:inManagedObjectContext:]. I add the
object to the NSArrayController by calling addObject:. The
addObject: message, however, doesn't seem to be necessary for
reasons I don't fully understand.
When you set "Automatically prepares content", the controller
observer notifications from the NSManagedObjectContext.
What I'm seeing is that the objects end up showing up in the
NSTableView as each one is imported. This didn't happen before I
added the sheet and thread. It appears that the table is observing
the insertions and trying to update -- which really slows down the
import process.
My question is -- is there any way I can turn off this update of
the NSTableView until I'm done? Can I create instances of managed
objects and then add them to the managed context all at once?
No, but you can probably turn off "Automatically prepares content"
during the import. (I haven't tried that)
This smells funny. DO NOT use the NSManagedObjectContext bound to
your controllers outside the main thread.
Question 3: During a long import, the update of the NSTableView
often stops after a number of rows are inserted. (It appears to
always be powers of 2 -1, eg 63, 255) Sometimes, I get bad access
exceptions during this update process. This makes me thing I'm
doing something wrong in this multi-threaded environment.
The exceptions are probably race conditions.
My progress bar also seems to jump back and forth a bit, even
though I'm steadily increasing the value passed to setDoubleValue:,
and I don't change the maximum value after the import starts.
I believe NSProgressIndicator isn't thread safe either. Somebody
correct me if I am wrong.
You should try to do the import in the main thread. The sheet does
not prevent that. You want to surrender the CPU to the run loop at
regular intervals in order to update the screen, respond to "Cancel"
buttons, and generally avoid the spinning beach ball. You can get the
run loop to call you back using [self performSelector:afterDelay:] or
NSNotificationQueue. This is cooperative multitasking.
If you really must use a thread, here is how to do it:
Create a new NSManagedObjectContext, hook it up to your
NSPersistentStoreCoordinator, and use only the new context from the
thread.
Always use -[performSelectorOnMainThread:] to send messages back,
even for the NSProgressIndicator.
When you are done, save the context and get rid of it. Watch out for
retain cycles caused by relationships.
Back in the main thread, tell your controller to fetch the new rows.
This method works well if you are only inserting new objects. If you
are updating existing objects, you need to refresh those in the main
context. If you are deleting objects, things get funky. If you are
using transient properties the way it is described in the docs and
examples, you're in trouble.
By the way, your export being "OK" is just luck. If you are not
creating a new NSManagedObjectContext for your thread, it too will
break some day.
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden