2009-12-08 67 views
0

我从NSThread派生的类: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?

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

回答

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()); 
} 
+0

CFRunLoopRun()之前,不会返回CFRunLoopStop()被调用;因此,我的main()无法检查isCancelled。我覆盖了取消方法来调用CFRunLoopStop()。所以现在停止线程,我正在做[m_thread取消],然后是[m_thread发布],并且工作。问题:重写取消方法是一件好事吗?文件没有说不应该。 – 2009-12-08 19:04:30

+0

这取决于你在做什么,但总的来说,我会说不,不这样做。最简单的方法是添加一个像finishThread这样的方法;我会在我的答案中添加一个快速示例。在CFRunLoopRun()函数返回后,您还应该执行所需的清理。 – 2009-12-08 19:36:48