Re: Thread Communication Conceptual Question
Re: Thread Communication Conceptual Question
- Subject: Re: Thread Communication Conceptual Question
- From: Alastair Houghton <email@hidden>
- Date: Thu, 2 Aug 2007 14:34:57 +0100
On 2 Aug 2007, at 12:36, Eyal Redler wrote:
Of course, you'd never write the above in a full-blown Cocoa
application, right? Because if you did, you'd block event
processing and your app would beachball.
Yes, I need the host application to continue normally and not hang
on waiting for the sub-thread.
Well -performSelectorOnMainThread:withObject:waitUntilDone: is the
simplest way to do that, passing NO for the waitUntilDone: argument.
Using a run loop source, or -
performSelectorOnMainThread:withObject:waitUntilDone: is a better
bet (though the above will work fine for a Foundation tool, for
instance).
Could you elaborate a bit about the run loop source?
Sure. You need to look at the CoreFoundation docs relating to run
loops:
<http://developer.apple.com/documentation/CoreFoundation/Conceptual/
CFRunLoops/index.html>
The Cocoa NSRunLoop and Carbon's EventLoop are both implemented on
top of CFRunLoop, and you can create your own run loop sources, which
allows you to add your own objects to the NSRunLoop.
It's a slightly complicated wait of solving the problem, but it
integrates nicely with the frameworks; indeed, NSStreams and
CFSockets work using CFRunLoopSources underneath.
Essentially you'd need to create a CFRunLoopSource for your object
(probably a version 0 source), then, when you want to signal the main
thread, call CFRunLoopSourceSignal() followed by CFRunLoopWakeUp() on
the run loop you're object was added to. You'd then implement the
CFRunLoopPerformCallBack() function in your callbacks (which you
specify when you create the run loop source) to call your object's
delegate or to dispatch a notification or something.
It's probably overkill for most situations, but, as I say, it's the
way some of the framework's own objects do this and it works very
nicely.
My original thought was that could just raise a flag (protected by
a lock, of-course) that the main thread watches but I didn't know
how to watch the flag while still processing events normally.
So to phrase it more generally, assuming that I have a global
status variable which is set by any thread, how can I watch it from
the main thread?
The only thing I could think of is setting a repeating timer with a
small interval on the main thread which checks the variable
state... I wonder if this is a viable method and if so, what would
be a good interval...
It depends what your status variable is for.
For instance, if it's just a progress value, then checking it every
so often is a perfectly good way to do it; you're only going to be
checking it whilst your application is busy, and it stops your app
from ending up being throttled by e.g. the number of -
performSelectorOnMainThread:withObject:waitUntilDone: calls you can
do in a single second. It also means that you won't be trying to
update the progress meter a thousand times a second, which is clearly
excessive. (Of course, there are other ways to prevent those
problems that don't use a timer, but they're more complicated. Using
a timer is a straightforward and simple solution.)
If, however, you're just waiting for some event to occur, then it
probably isn't the right way to do it (not least because naïvely
doing this can cause problems).
-performSelectorOnMainThread:withObject:waitUntilDone: is the
simplest method in most cases. In the absence of a good reason for
doing anything else, I'd be inclined to use that.
Kind regards,
Alastair.
--
http://alastairs-place.net
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please 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