NSRunLoopオブジェクトがあり、それにタイマーとストリームをアタッチします。それは素晴らしい働きをします。それをやめることは、まったく別の話です。
を使用してループを実行します[runLoop run]
。
を使用してループを停止しようとするとCRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop])
、ループが停止しません。CRunLoopRun()
代わりにを使用してループを開始すると、機能します。また、呼び出しが正しいスレッド(カスタム実行ループを実行しているスレッド)で行われることを確認しました。私はこれをでデバッグしましたpthread_self()
。
メーリングリストのアーカイブを見つけました。開発者は、「CRunLoopStop()
のrunメソッドを使用してループを開始した場合は、わざわざ使用しないでください」と言っていますNSRunLoop
。なぜそうなのか理解できます。通常、同じ関数セットのイニシャライザーとファイナライザーをペアにします。
NSRunLoop
「CFに頼る」ことなく、どうやってやめますか?stop
にメソッドが表示されませんNSRunLoop
。ドキュメントには、3つの方法で実行ループを停止できると書かれています。
- タイムアウト値で実行するように実行ループを構成します
- 実行ループに使用を停止するように指示します
CFRunLoopStop()
- すべての入力ソースを削除しますが、これは実行ループを停止するための信頼性の低い方法です。これは、背後の実行ループに何が詰まっているのかがわからないためです。
さて、私はすでに2を試しましたが、CFを掘り下げる必要があるため、「醜い」感じがします。3.問題外です-非決定論的なコードは好きではありません。
これにより、1が残ります。ドキュメントを正しく理解している場合、既存の実行ループにタイムアウトを「追加」することはできません。新しい実行ループは、タイムアウト付きでのみ実行できます。新しい実行ループを実行しても、ネストされた実行ループしか作成されないため、問題は解決しません。私はまだ古いものにすぐに戻ります、私が止めたかったのと同じです...そうですか?これを誤解したかもしれません。また、タイムアウト値を使用してループを実行したくありません。その場合、CPUサイクルの書き込み(タイムアウト値が低い)と応答性(タイムアウト値が高い)の間でトレードオフを行う必要があります。
これは私が今持っているセットアップです(擬似コードっぽい):
Communicator.h
@interface Communicator : NSObject {
NSThread* commThread;
}
-(void) start;
-(void) stop;
@end
Communicator.m
@interface Communicator (private)
-(void) threadLoop:(id) argument;
-(void) stopThread;
@end
@implementation Communicator
-(void) start {
thread = [[NSThread alloc] initWithTarget:self
selector:@selector(threadLoop:)
object:nil];
[thread start];
}
-(void) stop {
[self performSelector:@selector(stopThread)
onThread:thread
withObject:self
waitUntilDone:NO];
// Code ommitted for waiting for the thread to exit...
[thread release];
thread = nil;
}
@end
@implementation Communicator (private)
-(void) stopThread {
CRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]);
}
-(void) threadLoop:(id) argument {
// Code ommitted for setting up auto release pool
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
// Code omitted for adding input sources to the run loop
CFRunLoopRun();
// [runLoop run]; <- not stoppable with
// Code omitted for draining auto release pools
// Code omitted for signalling that the thread has exited
}
@endif
どうしようかな?CFをいじるのは一般的/良いパターンですか?私は財団を十分に知りません。CF層への干渉はおそらく危険ですか(メモリの破損、不整合、メモリリークに関して)?私が達成しようとしていることを達成するためのより良いパターンはありますか?