Ho un oggetto NSRunLoop, a cui aggiungo timer e flussi. Funziona alla grande. Fermarlo è un'altra storia in tutto e per tutto.CFRunLoopRun() vs [NSRunLoop run]
Corro il ciclo utilizzando [runLoop run]
.
Se provo a interrompere il ciclo utilizzando CRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop])
, il ciclo non si interromperà. Se avvio il ciclo usando invece CRunLoopRun()
, funziona. Mi sono anche assicurato che la chiamata sia fatta sul thread corretto (quello che esegue il mio ciclo di esecuzione personalizzato). Ho effettuato il debug di questo con pthread_self()
.
Ho trovato un archivio di mailing list, in cui uno sviluppatore ha detto "non preoccupatevi di usare CRunLoopStop()
se avete iniziato il ciclo usando il metodo di esecuzione di NSRunLoop
". Posso capire perché è così com'è: di solito si accoppiano inizializzatori e finalizzatori dello stesso insieme di funzioni.
Come si ferma uno NSRunLoop
senza "ricorrere a CF"? Non vedo un metodo stop
su NSRunLoop
. La documentazione dice che ci si può fermare un ciclo corsa in tre modi:
- Configurare il ciclo di esecuzione per l'esecuzione con un valore di timeout
- Dillo ciclo corsa di smettere di usare
CFRunLoopStop()
- Rimuovere tutte le sorgenti di ingresso, ma questo è un modo affidabile per fermare il ciclo di periodo, perché si può mai sapere che cosa bloccato quello che nel circuito corsa dietro la schiena
Beh, ho già provato 2. e non c'è un "brutto" si sentono ad essa, perché si scavare nella CF. 3. è fuori questione - non mi piace il codice non deterministico.
Questo ci lascia 1. Se capisco correttamente i documenti, non è possibile "aggiungere" un timeout a un ciclo di esecuzione già esistente. È possibile eseguire solo nuovi cicli di esecuzione con un timeout. Se eseguo un nuovo ciclo di esecuzione, non risolverà il mio problema, poiché creerà solo un ciclo di esecuzione annidato. Continuerò a tornare al vecchio, lo stesso che volevo fermare ... giusto? Potrei aver frainteso questo. Inoltre, non voglio eseguire il ciclo con un valore di timeout. Se lo faccio, dovrò fare un compromesso tra la masterizzazione dei cicli della CPU (basso valore di timeout) e la reattività (alto valore di timeout).
Questa è la configurazione che ho in questo momento (pseudo codice-ish):
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
Che cosa sono io fare? È comune/un buon modello per scherzare con CF? Non conosco abbastanza bene la Fondazione. L'interferenza nello strato CF può essere pericolosa (rispetto alla corruzione della memoria, incoerenze, perdite di memoria)? C'è uno schema migliore per ottenere ciò che sto cercando di ottenere?
Ah, intelligente! Non ho visto che 'runMode' ha funzionato solo una volta. C'è una significativa penalità per le prestazioni subita dall'inizio del ciclo di corse più e più volte? –
No, non c'è: ecco come funzionano '- [NSRunLoop run]' e '- [NSRunLoop runUntilDate:]'. –
Il thread non si fermerà se si imposta solo runLoopIsStopped su YES. È necessario impostarlo su SÌ ed eseguire un'azione sul thread di quel runloop, altrimenti [runLoop runMode: NSDefaultRunLoopMode beforeDate: date] non verrà chiuso. Mi ci sono voluti anni per capire. – Pada