使用 [NSThread detachNewThreadSelector:toTarget:withObject:] 时如何设置自动释放池
Posted
技术标签:
【中文标题】使用 [NSThread detachNewThreadSelector:toTarget:withObject:] 时如何设置自动释放池【英文标题】:How to set up an autorelease pool when using [NSThread detachNewThreadSelector:toTarget:withObject:] 【发布时间】:2011-03-18 09:36:08 【问题描述】:您好,我正在使用 [NSThread detachNewThreadSelector:toTarget:withObject:] 并且我遇到了很多内存泄漏,因为我没有为分离的线程设置自动释放池。我只是想知道我实际上在哪里做这个?是在我打电话之前吗
[NSThread detachNewThreadSelector:toTarget:withObject:]
还是在另一个线程中正在运行的方法中?
任何帮助将不胜感激,一些示例代码会很棒。
谢谢。
【问题讨论】:
@user636866:在我看来,Simon Lee 的回答是最容易理解和切中要害的。尽管其他人也值得为他们的努力投票。 【参考方案1】:在你用线程调用的方法中......即给定这个......
[NSThread detachNewThreadSelector:@selector(doStuff) toTarget:self withObject:nil];
你的方法是……
- (void)doStuff
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//Do stuff
[pool release];
【讨论】:
对于 ARC,请参阅 this thread【参考方案2】:你必须在你调用的方法中设置一个自动释放池,它将在新的分离线程中执行。
例如:
// Create a new thread, to execute the method myMethod
[NSThread detachNewThreadSelector:@selector(myMethod) toTarget:self withObject:nil];
和
- (void) myMethod
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Here, add your own code
// ...
[pool drain];
请注意,我们在 autoreleasepool 上使用 drain 而不是 release。在 ios 上,它没有区别。在 Mac OS X 上,如果您的应用程序被垃圾回收,它将触发垃圾回收。这使您可以编写可以更轻松地重复使用的代码。
【讨论】:
【参考方案3】:创建新线程:
[NSThread detachNewThreadSelector:@selector(myMethod) toTarget:self withObject:nil];
创建新线程调用的方法。
- (void)myMethod
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Your Code
[pool release];
如果您需要从新线程内部对主线程执行某些操作(例如,显示加载符号)怎么办?使用 performSelectorOnMainThread。
[self performSelectorOnMainThread:@selector(myMethod) withObject:nil waitUntilDone:false];
参考:-iPhone SDK Examples
【讨论】:
【参考方案4】:在您调用的方法中执行此操作。本质上,您应该将被调用的方法设置为一个独立的工作单元(事实上,它也将与通过[NSOperation][1]
或Grand Central Dispatch 调用兼容:这两种组织并发工作的更好方法) .
但是如果我无法更改我在新线程上调用的方法的实现怎么办?
在这种情况下,您将不再这样做:
[NSThread detachNewThreadSelector: @selector(blah:) toTarget: obj withObject: arg]
这样做:
[NSThread detachNewThreadSelector: @selector(invokeBlah:) toTarget: self withObject: dict]
- (void)invokeBlah: (id)dict
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id obj = [dict objectForKey: @"target"];
id arg = [dict objectForKey: @"argument"];
[obj blah: arg];
[pool release];
您也可以创建一个封装远程对象调用的NSInvocation,而不是使用字典。我只是选择了一本字典,因为它是在 SO 答案中显示情况的最快方法。两者都行。
【讨论】:
【参考方案5】:文档声明线程中运行的方法必须创建和销毁自己的自动释放池。所以如果你的代码有
[NSThread detachNewThreadSelector:@selector(doThings) toTarget:self withObject:nil];
方法应该是
- (void)doThings
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//Do your things here
[pool release];
【讨论】:
以上是关于使用 [NSThread detachNewThreadSelector:toTarget:withObject:] 时如何设置自动释放池的主要内容,如果未能解决你的问题,请参考以下文章