开发者

Background thread NSRunloop run does not exit after NSTimer is invalidated! Why?

I'm creating an NSTimer and adding it to the runloop of a background thread. My code is like the background thread example for this answer: iPhone-SDK:Call a function in the background?

After creating the timer and attching it to the runloop from gdb I po runLoop and it outputs this:

<CFRunLoop 0x695b090 [0x16a62c0]>{wakeup port = 0x6907, stopped = false,
current mode = kCFRunLoopDefaultMode,
common modes = <CFBasicHash 0x6936e60 [0x16a62c0]>{type = mutable set, count = 1,
entries =>
    1 : <CFString 0x16abba8 [0x16a62c0]>{contents = "kCFRunLoopDefaultMode"}
}
,
common mode items = <CFBasicHash 0x695e160 [0x16a62c0]>{type = mutable set, count = 1,
entries =>
    0 : <CFRunLoopTimer 0x69398a0 [0x16a62c0]>{valid = Yes, interval = 6, next fire date = 329774303, callout = __NSFireTimer (0x212399), context = <CFRunLoopTimer context 0x6903a10>}
}
,
modes = <CFBasicHash 0x6904120 [0x16a62c0]>{type = mutable set, count = 1,
entries =>
    1 : <CFRunLoopMode 0x6946180 [0x16a62c0]>{name = kCFRunLoopDefaultMode, port set = 0x6807, timer port = 0x6b03开发者_C百科, 
    sources0 = (null),
    sources1 = (null),
    observers = (null),
    timers = <CFArray 0x695e180 [0x16a62c0]>{type = mutable-small, count = 1, values = (
    0 : <CFRunLoopTimer 0x69398a0 [0x16a62c0]>{valid = Yes, interval = 6, next fire date = 329774303, callout = __NSFireTimer (0x212399), context = <CFRunLoopTimer context 0x6903a10>}
)}
},

}
}

This shows that 1 timer is attached to the runloop Later after I invalidate the timer the NSRunloop run method doesn't exit but after I pause the debugger and from gdb I po runLoop again it looks like this:

<CFRunLoop 0x695b090 [0x16a62c0]>{wakeup port = 0x6907, stopped = false,
current mode = kCFRunLoopDefaultMode,
common modes = <CFBasicHash 0x6936e60 [0x16a62c0]>{type = mutable set, count = 1,
entries =>
    1 : <CFString 0x16abba8 [0x16a62c0]>{contents = "kCFRunLoopDefaultMode"}
}
,
common mode items = <CFBasicHash 0x695e160 [0x16a62c0]>{type = mutable set, count = 0,
entries =>
}
,
modes = <CFBasicHash 0x6904120 [0x16a62c0]>{type = mutable set, count = 1,
entries =>
    1 : <CFRunLoopMode 0x6946180 [0x16a62c0]>{name = kCFRunLoopDefaultMode, port set = 0x6807, timer port = 0x6b03, 
    sources0 = (null),
    sources1 = (null),
    observers = (null),
    timers = <CFArray 0x695e180 [0x16a62c0]>{type = mutable-small, count = 0, values = ()}
},

}
}

Now the "timers" entry has 0 objects. But the thread continues to run. I often leave the screen then come back so this leads to a build up of background threads which will eventually kill the app after too many resources are used. The timers don't fire after they are invalidated but the background thread remains.

I know I can move timers back to the main thread or create my own simple timer thread with NSThread sleepForTimeInterval but I would like to keep the main thread for GUI updates and use NSTimer if possible.


This stops a run loop fine for me:

[[NSRunLoop currentRunLoop] runUntilDate: [NSDate date]];

If you're writing code which may be run on the main thread (and hence uses the main runloop) though, you should check to see if your current runloop is the main runloop before doing this - otherwise you'll bomb your app.

// Kill the runloop now.
NSRunLoop* rl = [NSRunLoop currentRunLoop]; // Get the runloop
if (rl != [NSRunLoop mainRunLoop])
{
    // Set it running again, but only until now. 
    // In other words, STOP!!!
    [rl runUntilDate: [NSDate date]];
}


From the -[NSRunLoop run] docs:

Manually removing all known input sources and timers from the run loop is not a guarantee that the run loop will exit.

You should use a different method, possibly runMode:beforeDate: in a loop, and, at the same time you invalidate the timer, set a flag indicating that the run loop should end.


I needed to read the documentation for [NSTimer invalidate].... This method must be called from the same thread in which the timer is installed. If you don't call it from the same thread the timer thread will not exit.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜