У меня есть объект NSRunLoop, к которому я присоединяю таймеры и потоки. Работает отлично. Остановка это совсем другая история.
Я запускаю цикл, используя [runLoop run]
.
Если я попытаюсь остановить цикл, используя CRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop])
, цикл не остановится. Если вместо этого я запускаю цикл, используя CRunLoopRun()
, он работает. Я также удостоверился, что вызов сделан в правильном потоке (тот, который выполняет мой пользовательский цикл выполнения). Я отладил это с pthread_self()
.
Я нашел архив списка рассылки, в котором разработчик сказал: «Не утруждайте себя использованием CRunLoopStop()
, если вы запустили цикл с помощью метода run NSRunLoop
». Я могу понять, почему это так - вы обычно объединяете инициализаторы и финализаторы из одного и того же набора функций.
Как вы можете остановить NSRunLoop
без "обращения к CF"? Я не вижу stop
метод на NSRunLoop
. В документе сказано, что вы можете остановить цикл выполнения тремя способами:
- Конфигурирование цикла выполнения для запуска со значением времени ожидания
- Скажите циклу выполнения прекратить использование
CFRunLoopStop()
- Удалите все входные источники, но это ненадежный способ остановить цикл выполнения, потому что вы никогда не можете знать, что застряло в цикле выполнения за вашей спиной
Ну, я уже попробовал 2. и это вызывает "уродливое" чувство, потому что вы должны копаться в CF. 3. не может быть и речи - мне не нравится недетерминированный код.
Это оставляет нам 1. Если я правильно понимаю документы, вы не можете «добавить» тайм-аут в уже существующий цикл выполнения. Вы можете запускать только новые циклы выполнения с таймаутом. Если я запускаю новый цикл выполнения, это не решит мою проблему, так как он создаст только вложенный цикл выполнения. Я все равно вернусь к старому, то же самое, что я хотел остановить ... верно? Возможно, я неправильно понял это. Кроме того, я не хочу запускать цикл со значением тайм-аута. Если я это сделаю, мне придется сделать компромисс между записью циклов ЦП (низкое значение тайм-аута) и отзывчивостью (высокое значение тайм-аута).
Это настройка, которая у меня есть сейчас (псевдокод):
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 (в отношении повреждения памяти, несоответствий, утечек памяти)? Есть ли лучший шаблон для достижения того, чего я пытаюсь достичь?