Re: NSRunLoop looping more than once?
Re: NSRunLoop looping more than once?
- Subject: Re: NSRunLoop looping more than once?
- From: John Anderson <email@hidden>
- Date: Mon, 17 Mar 2003 01:44:33 -0500
Dear Julein,
Thanks for responding to my question. For the benefit of other
readers, I am going to try summarize my newfound understanding of the
relationship between NSTimer and NSRunLoop in this post.
(1) As Apple's Chris Kane has previously stated, a simple way to
cleanly exit from a NSRunLoop (and perhaps cleanly terminate a
NSThread) is like so:
while(running)[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]];
where "running" is a BOOL that is originally set to YES and can be
toggled by another thread or some other sequence of events.
(2) The problem that we have both apparently ran into is that
[NSRunLoop runMode: beforeDate] does not return after the "NSRunLoop
"runs the loop once" and "returns after ... the first input is
processed" (as clearly implied by Apple's current NSRunLoop
documentation) when the "input" to the NSRunLoop is a repeating
NSTimer. So the code fails to poll the status to the "running" BOOL
and thus fails to stop the NSRunLoop from continuing to run.
Furthermore, while calling [NSTimer invalidate] does stop the timer
from firing, the [NSRunLoop runMode: beforeDate] still does not return.
However, a non-repeating NSTimer appears to act like a normal "input"
to NSRunLoop in that [NSRunLoop runMode: beforeDate] does return after
the timer fires.
(3) Now by Chris Kane's latest post, this is not a bug in NSRunLoop but
rather the intended behavior. Moreover, Chris advises us to be wary of
two other related scenarios that are potential pitfalls in
understanding the behavior of [NSRunLoop runMode: beforeDate]. First,
what exactly constitutes the processing of the "first input" may
greatly be extended by recursive calls on the NSRunLoop triggered by
the original input signal. Second, if the NSRunLoop is monitoring
multiple input signals in its active mode, more than one signal might
be processed in the same loop of execution and therefore which trying
to determine which signal actually caused [NSRunLoop runMode:
beforeDate] to return may be impossible.
(4) For a number of reasons, calling CFRunLoopStop (as you suggest) is
probably not the best solution to the dealing with the fact that
[NSRunLoop runMode: beforeDate] does not return from repeating
NSTimers. Again as previously indicated by Chris Kane, using
[NSRunLoop acceptInputForMode: beforeDate:[NSRunLoop
limitDateForMode:]] is the way this is "supposed to be done." So, the
preferred way to cleanly exit from a NSRunLoop driving by a repeating
NSTimer is like so:
while(running)[[NSRunLoop currentRunLoop]
acceptInputForMode:NSDefaultRunLoopMode beforeDate:[[NSRunLoop
currentRunLoop] limitDateForMode:NSDefaultRunLoopMode]];
Truly yours,
John Philip Anderson
Detroit Michigan USA
On Sunday, Mar 16, 2003, at 11:07 America/Detroit, Julien Jalon wrote:
On mercredi, mars 12, 2003, at 06:48 Europe/Paris, John Anderson wrote:
Dear List,
According to Apple's documention, calling runMode: beforeDate: on
NSRunLoop "runs the loop once" and "returns after ... the first input
is processed.
So with the following code:
myTimer = [NSTimer timerWithTimeInterval:timeInterval target:self
selector:@selector(myMethod) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:myTimer
forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]];
I would expect to have "myMethod" called once when "myTimer" fires and
then control to passed on done the line.
However, this is not what happens. In fact, the NSRunLoop appears to
loop indefinitely and calls "myMethod" every time "myTimer" fires, as
if I had called run or runUntilDate: on it.
Is this supposed to happen?
If so, then what do "loop once" and "return after ... the first input
in processed" really mean?
I found this exact same problem while implementing some sort of a Time
out. A timer seems not to trigger the "run loop handled a source"
trick. I think we can consider it a bug but you have to use a
workaround here if you want your call to runMod:beforeDate: to return
even after a timer firing:
- (void)timerFired:(NSTimer *)aTimer {
// do all your work
CFRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]);
}
--
Julien Jalon
http://www.julien-jalon.org/
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.