Re: bindings from threads
Re: bindings from threads
- Subject: Re: bindings from threads
- From: Chris Hanson <email@hidden>
- Date: Thu, 5 Oct 2006 21:07:26 -0700
On Oct 5, 2006, at 11:33 AM, Ryan Britton wrote:
The approach to take has two parts. Since bindings are typically
used to update UI widgets, the update notifications need to be
called on the main thread. A typical update may look something like
this:
[self performSelectorOnMainThread:@selector(willUpdateValueForKey:)
withObject:@"someKey" waitUntilDone:YES];
//Update the value for someKey
[self performSelectorOnMainThread:@selector(didUpdateValueForKey:)
withObject:@"someKey" waitUntilDone:YES];
That handles the first part. For the second part you need to make
sure your accessors are threadsafe. You can either accomplish this
with locks or any of the other various thread safety directives or
ensure that values are only updated on the main thread.
The above is not what you should do. In particular, you should not be
using main-thread performs to post KVO change notifications that are
distinct from the actual change to your object.
To see why the above is broken, consider this scenario:
(1) Thread 2 asks the main thread to perform the following, which it
does:
[self willChangeValueForKey:@"someKey"];
Then there's a random context switch.
(2) Something on the main thread also changes that object, which
invokes the following:
[self willChangeValueForKey:@"someKey"];
_someKey = @"foo";
Then there's a random context switch.
(3) Thread 2 happens to be chosen to run again, which does the
following:
_someKey = @"bar";
and then asks the main thread to perform the following:
[self didChangeValueForKey:@"someKey"];
Then there's a random context switch.
(4) The main thread finally executes:
[self didChangeValueForKey:@"someKey"];
Congratulations! The state of your object is all messed up now, and
that corruption is propagating to the observers of the key "someKey"
-- especially if they were interested in the old and/or new values of
the key for some purpose.
Also, "thread-safe" accessors are almost *never* what you want;
typically an object has enough state that thread safety needs to be
treated as a way of delineating *transactions* on an object or even
the entire graph of related objects. This is necessary to prevent the
object graph from becoming inconsistent when there can be multiple
clients performing operations on it.
As I've said before, if you're considering doing *anything* with
threads, you should follow well-established patterns of use such as
producer/consumer work queues. You cannot just dive in to creating
multithreaded applications by throwing a thread in here and a thread
in there to "make things faster." It not only doesn't work, it can be
harmful to both the stability and performance of your application.
-- 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