NSThread对象保留两次?

时间:2009-12-08 17:25:07

标签: objective-c cocoa release nsthread retain

我有一个派生自NSThread的课程:

@interface FSEventMonitorThread : NSThread {
    FSEventStreamRef m_fseStreamRef;
    CFRunLoopRef m_runLoop;
}

- (id) initWithStream:
    (FSEventStreamRef)fseStreamRef;

- (void) dealloc;

- (void) main;

@end

@implementation FSEventMonitorThread

- (id) initWithStream:
    (FSEventStreamRef)fseStreamRef
{
    if ( self = [super init] )
        m_fseStreamRef = fseStreamRef;
    return self;
}

 - (void) dealloc
{
    CFRunLoopStop( m_runLoop );
    FSEventStreamStop( m_fseStreamRef );
    [super dealloc];
}

- (void) main
{
    m_runLoop = CFRunLoopGetCurrent();
    FSEventStreamScheduleWithRunLoop(
        m_fseStreamRef, m_runLoop, kCFRunLoopDefaultMode
    );
    FSEventStreamStart( m_fseStreamRef );
    CFRunLoopRun();
}

@end

在其他地方(在C ++函数中),我创建了一个实例:

m_thread = [[FSEventMonitorThread alloc] initWithStream:m_fseStreamRef];

我的理解是,保留计数现在应为1。 在另一个C ++函数中,我想停止并取消分配线程:

[m_thread release];

然而,dealloc方法未被调用。如果我改为:

[m_thread release];
[m_thread release];

然后调用dealloc,这意味着保留计数为2.但它是如何变为2?

请注意,NSThread的文档仅提及在使用detachNewThreadSelector:toTarget:withObject:时保留。

1 个答案:

答案 0 :(得分:3)

框架本身保留了线程的所有权。这是必要的,以便在执行main方法时线程对象不会消失。如果你想停止一个线程,你的做法是错误的。您必须提供某种线程间通信,以通知线程的主要方法,它应该停止它正在做的任何事情,清理和退出。一旦发生这种情况,放弃对线程的所有权将导致线程解除分配。你永远不应该过度释放一些东西让它“消失”。如果你这样做,你几乎肯定不会按照它们的使用方式使用提供的对象,就像在这种情况下一样。

取消线程的一个非常简单的示例可能是:

- (void)finishThread
{
  if( [NSThread currentThread] != self ) // dispatch this message to ourself
    [self performSelector:@selector(finishThread) onThread:self withObject:nil waitUntilDone:NO];
  else
    CFRunLoopStop(CFRunLoopGetCurrent());
}