Re: Cocoa binding and threads.
Re: Cocoa binding and threads.
- Subject: Re: Cocoa binding and threads.
- From: Chris Hanson <email@hidden>
- Date: Tue, 15 Aug 2006 19:55:16 -0700
On Aug 14, 2006, at 10:18 AM, David Burnett wrote:
I'm attempting to multi-thread my Cocoa application which is
heavily based on Cocoa Bindings using Core Data and I'm having GUI
update issues.
Do not modify objects that are bound to in anything but the main thread.
At the moment it all works fine except that NSTableView that displays
the values from the Entities in the Managed Context does not update
on adding a new entity until either
I click on the window.
Move the mouse over a control that changes the cursor.
Change focus on/off the window.
They worked fine before I started to run this code of a new thread.
It sounds like you just took the logic that was on your main thread
and wrapped it in -[NSThread
detachNewThreadSelector:toTarget:withObject:]. Is that what you did?
If so, it would mean that you have multiple threads accessing or
changing the same managed object at the same time: The main thread,
since the managed object is bound to, and your detached thread.
Core Data does not support this access pattern. A managed object
context must only be accessed from a single thread at a time, and
never by multiple threads simultaneously. Furthermore, any access to
a managed object involves an access to the managed object context it
is registered with.
Also, Cocoa bindings and key-value observing are not thread-safe.
They also do not provide the hooks necessary to make them thread-
safe. Thus you cannot take a managed object that is being observed
by a control in your human interface -- for example, an object that
is being shown in a table via bindings -- and manipulate or even
access it on another thread.
I understand that Bindings do not play to well with threads as the
GUI changes occur in the same thread as the value changes, and
Cocoa prefers it GUI changes in the main thread. To this end my
thread runs like this
AddRandomGenomeToFlamesUsingContext
createRandomGenomeInContext
RenderThumbnail
createGenomeEntity (on main thread)
addNewFlame (on main thread)
The new Entity is created in createGenomeEntity and one of its
values is changed in AddNewFlame. Both are called using
performSelectorOnMainThread: withObject: waitUntilDone:YES so all of
the changes in the bound values should be performed on the main
thread.
AddRandomGenomeToFlamesUsingContext is detached from an Action
responding to a button press.
From the above, it sounds like you're still *accessing* managed
objects associated with the same managed object context used by the
controls in your main thread on your detached thread. That's not
supported, because it could still result in the context being
manipulated from multiple threads at the same time without
appropriate locking.
Also, as I describe above, you can't perform the necessary locking
for a context used by controls via bindings because you don't have
the necessary hooks into the controls to add the locking.
If you want to perform this operation on a separate thread, you'll
have to create a separate context on that thread and connect it to
the same persistent store coordinator Then when you make changes on
your detached thread, you can save those changes to your persistent
store, send the collection of object IDs that changed over to the
main thread, and refresh those objects in the context you're using in
the main thread.
-- Chris
_______________________________________________
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