使用 NSThread 进行内存管理
我有一个应用程序需要用莫尔斯电码连续发出一个单词的信号。我通过创建一个 NSThread 并使用“while 循环”在选择器内运行一些代码来做到这一点。下面是代码:
@implementation MorseCode
-(void)startContinuousMorseBroadcast:(NSString *)words{
if (!(threadIsOn)) {
threadIsOn = YES; s
myThread = [[NSThread alloc] initWithTarget:self selector:@selector(threadSelector:) object:words];
[myThread start];
}
if (morseIsOn) {
morseIsOn = NO;
}
else{
morseIsOn = YES;
}
}
-(void)threadSelector:(NSString *)words{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
while (![myThread isCancelled]) {
// ///it Does some code here
} //end While
NSLog(@"Cleaning the pool");
[pool drain];
}
@end
退出应用程序时(用户按下按钮),在 applicationDidEnterBackground 中执行以下选择器:
-(void)cleanUpMorseObject{ //this is defined in the MorseCode class, same as threadSelector
if (threadIsOn) {
NSLog(@"cleanUpMorseObject, threadIsOn");
threadIsOn = NO;
morseIsOn = NO;
[myThread cancel];
[myThread release];
}
}
应用程序正确响应事件,我已使用 nslog 检查过。 然后[摩尔斯电码释放]被调用。 代码如下所示:
-(void)applicationDidEnterBackground{ //this happens in the ViewController
[theMorse cleanUpMorseObject]; //theMorse is an instance of MorseCode
[theMorse release];
}
问题:虽然我调用 [myThread release] 然后调用 [theMorse release] theMorse 的保留计数仍然高于 0 (它不调用dealloc)。
Leaks Instrument 并没有说我有泄漏,但如果我打开和关闭应用程序大约 10 次,iPhone 最终会重置。同样在调试器中,我最终看到“收到内存警告。级别=2”。
另外,我从来没有在池排水之前看到 NSLog…
该应用程序不在后台运行。 有什么想法吗?谢谢
I have an app that needs to signal continuously a word in morse code. I did this by creating an NSThread and running some code inside the selector with a "while loop". Here is the code:
@implementation MorseCode
-(void)startContinuousMorseBroadcast:(NSString *)words{
if (!(threadIsOn)) {
threadIsOn = YES; s
myThread = [[NSThread alloc] initWithTarget:self selector:@selector(threadSelector:) object:words];
[myThread start];
}
if (morseIsOn) {
morseIsOn = NO;
}
else{
morseIsOn = YES;
}
}
-(void)threadSelector:(NSString *)words{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
while (![myThread isCancelled]) {
// ///it Does some code here
} //end While
NSLog(@"Cleaning the pool");
[pool drain];
}
@end
When exiting the application (the user presses the button), in the applicationDidEnterBackground the following selector is executed:
-(void)cleanUpMorseObject{ //this is defined in the MorseCode class, same as threadSelector
if (threadIsOn) {
NSLog(@"cleanUpMorseObject, threadIsOn");
threadIsOn = NO;
morseIsOn = NO;
[myThread cancel];
[myThread release];
}
}
The application responds correctly to the event, I’ve checked with nslog.
And then [MorseCode release] is called.
The code looks like this:
-(void)applicationDidEnterBackground{ //this happens in the ViewController
[theMorse cleanUpMorseObject]; //theMorse is an instance of MorseCode
[theMorse release];
}
The problem: Although I call [myThread release] and then [theMorse release] the retainCount of the theMorse is still above 0 (It doesn’t call the dealloc).
The Leaks Instrument doesn’t say I have a leak, but if I open and close the application for like 10 times eventually the Iphone resets. Also in the debugger eventually I see the “Received memory warning. Level=2”.
Also I never see the NSLog before the pool drain…
The app doesn't run in the background.
Any ideas? Thank you
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您确实应该安排在 RunLoop 上发送消息,最简单的方法可能是安排计时器(无限重复,以及短重复周期,如 FLT_EPSILON 或类似的),而不是使用线程。
使用线程很复杂,每个人都应该避免它(正如 Apple 在其并发编程指南中所述,并且正如大多数文档所说,“线程是邪恶的”;))。
这是因为多线程是一个庞大而复杂的主题,需要同步、资源保护、了解死锁、临界区和线程。等等,良好且适应性强的内存管理等等。一般来说,如果您需要在后台执行操作:
performInBackground:
的方法这将避免你很多问题,因为所有其他更高的 API 都会为你处理很多事情。
此外,像您一样使用线程来执行此任务可能会使用更多的 CPU(可能会很快达到 100% 使用率),因为任务调度程序将没有任何时间(这也是为什么即使 GCD 会处理所有任务)这样的东西比 NSThreads 好得多,如果不需要强 RT 约束,那么在 RunLoop 中调度发送对于 CPU 来说甚至更好)
You really should schedule the sending of the message on the RunLoop, the probably easiest way being to schedule a timer (repeat infinitely, and short repeat period like
FLT_EPSILON
or similar) instead of using threads for that.Working with threads is complicated and as everyone should avoid it (as Apple stated in its Concurrency Programming Guide, and as most documentation said, "Threads are evil" ;)).
That's because multithreading is a vast and complicated subject, that needs synchronizations, resources protection, being aware of dead locks, critical sections & so on, good and adapted memory mgmt, and much much more. In general if you need to do stuff in the background:
performInBackground:
NSThread
.This will avoid you a lot of issues as all the other, higher APIs will take care of a lot of things for you.
Moreover, using threads for this task like you do is likely to use much more CPU (will probably reach 100% usage quickly) as there won't be any time left for the task scheduler (that also why even GCD that takes care of all stuff like that is way better than
NSThreads
, and scheduling the sending in the RunLoop is even better for the CPU if you don't need strong RT constraints)首先,retainCount永远不能返回0。这是一个无用的方法。别叫它。
其次,泄漏仅检测不再引用的对象。如果线程仍在运行,则不会泄漏。
最后,当您调用
cancel
时,线程不会停止。它只是设置一个标志,您必须通过 isCancelled 检查该标志,看看是否该停止线程中的工作。你在这样做吗?好的——简单的事情就回答了。下一个?尝试构建和分析。然后使用分配工具并打开引用计数跟踪。然后看看什么叫
retain
额外的时间。First,
retainCount
can never return 0. It is a useless method. Don't call it.Secondly, leaks only detects objects that are no longer referenced. If a thread is still running, it isn't leaked.
Finally, a thread doesn't stop when you call
cancel
. It just sets a flag that you have to check viaisCancelled
to see if it is time to stop work in the thread. Are you doing that?OK -- easy stuff answered. Next? Try build and analyze. Then use the Allocations instrument and turn on reference count tracking. Then see what is calling
retain
an extra time.我决定放弃 NSThread 类并使用另一种方法:
我希望这对某人有帮助:)
谢谢
I decided to give up the NSThread class and used another aproach:
I hope this helps somebody :)
Thank you