0

私はから派生したクラスを持っています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];

私の理解では、retain-countは1になっているはずです。別のC ++関数で、スレッドを停止して割り当てを解除したいと思います。

[m_thread release];

しかし、deallocメソッドは呼び出されません。代わりに私がする場合:

[m_thread release];
[m_thread release];

次にdealloc、retain-countが2であったことを意味するように呼び出されます。しかし、どのようにして2になったのでしょうか。

NSThread のドキュメントでは、を使用する場合の保持についてのみ言及していることに注意してくださいdetachNewThreadSelector:toTarget:withObject:

4

1 に答える 1

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());
}
于 2009-12-08T17:56:47.337 に答える