2013-05-10 18 views
5

Ho letto molti post su NSRunLoop, come this, this, this. Ma non riesco a capire cosa realmente fa NSRunLoopCosa fa NSRunLoop?

Quello che di solito vedo è un thread di lavoro

wthread = [[NSThread alloc] initWithTarget:self selector:@selector(threadProc) object:nil]; 
[wthread start]; 

con una NSRunLoop suo interno

- (void)threadProc 
{ 
    NSAutoreleasePool* pool1 = [[NSAutoreleasePool alloc] init]; 
    BOOL isStopped = NO; 
    NSRunLoop *runloop = [NSRunLoop currentRunLoop]; 
    [runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; 

    while (!isStopped) 
    { 
     { 
      NSAutoreleasePool* pool2 = [[NSAutoreleasePool alloc] init]; 
      [runloop runMode:NSDefaultRunLoopMode 
             beforeDate:[NSDate distantFuture]]; 

      [pool2 release]; 
     } 
    } 

    [pool1 release]; 
} 

E il filo conduttore passa un po 'di lavoro per questo wthread

[self performSelector:@selector(someWork:) onThread:wthread withObject:nil waitUntilDone:NO]; 

In termine di passaggio di lavoro dal thread principale al wor thread ker, vedo molte persone farlo. Perché hai bisogno di NSRunLoop qui? Che cosa fa ?

ho letto che NSRunLoop viene utilizzato per gestire gli eventi, perché c'è nulla se non chiamare RunMode all'interno threadProc?

+0

ci penso come una fantasia while (true) {// Inserire lavoro da fare qui}, dove è possibile aggiungere in modo dinamico il codice da eseguire (eventi, lavoro, prese ecc.). Il runloop non è veramente vuoto, una porta è stata collegata al runloop, è una forma di comunicazione tra processi. – foFox

+0

Ho trovato utile anche questo http://bou.io/RunRunLoopRun.html – onmyway133

risposta

3

L'esempio che hai mostrato è un idioma Cocoa per la creazione di un thread che continuerà a essere eseguito dopo le uscite del metodo -threadProc. Perché?

Perché:

  • l'istanza NSRunLoop che hai creato ha almeno una sorgente di ingresso ([NSMachPort port])
  • hai iniziato in modo esplicito il ciclo corsa con runMode:beforeDate

Senza l'aggiunta di un sorgente di input e avvio esplicito del ciclo di esecuzione, il thread terminerebbe.

Tra parentesi, anche se i cicli eseguiti sono ancora vitale per la gestione di eventi e alcuni compiti asincroni, non mi considero NSThread come il modo di default di architecting maggior parte del lavoro asincrono in un'applicazione Cocoa al giorno d'oggi. GCD è un modo molto più pulito di incapsulare il lavoro di sfondo.

EDIT:

Presentando il lavoro a una coda di serie in GCD:

@interface Foo : NSObject 
@end 

@implementation Foo { 
    dispatch_queue_t _someWorkerQueue; 
} 

- (id)init { 
    self = [super init]; 
    if(!self) return nil; 

    _someWorkerQueue = dispatch_queue_create("com.company.MyWorkerQueue", 0); 
    return self; 
} 

- (void)performJob { 
    dispatch_async(_someWorkerQueue, ^{ 
     //do some work asynchronously here 
    }); 

    dispatch_async(_someWorkerQueue, ^{ 
     //more asynchronous work here 
    }); 
} 
@end 
+0

1) Quindi perché c'è un ciclo all'interno di threadProc? 2) GCD trasferirà il lavoro su qualsiasi thread disponibile/sconosciuto, ma NSRunLoop assicurerà che tutto il lavoro verrà trasferito a questo stesso thread di lavoro, giusto? – onmyway133

+0

Per fornire un meccanismo per terminare il ciclo di esecuzione - quando è impostato il flag 'isStopped' (sebbene ciò non sia mostrato nel codice ...) – FluffulousChimp

+0

2) vedere la risposta modificata per l'approccio GCD al caso d'uso che si sta descrivendo. – FluffulousChimp

3

Molto va avanti dietro la scena. La ragione di ciò è che il thread interrompe l'esecuzione quando non ci sono elementi di lavoro. Se hai mai usato un sistema operativo in tempo reale, le attività hanno bisogno di un posto dove abbandonare il processore in modo che altri possano funzionare.

Ciò che non è ben documentato è che quando si invia performSelector: onThread: ..., è il ciclo di esecuzione che accoda il messaggio e si sveglia per consentire al thread di elaborarlo. Se aggiungi dei messaggi di log al ciclo while puoi vedere che succede.

Per i più curiosi c'è un codice di esempio su github con cui si può giocare con i loop di esecuzione - aggiungi un commento e ne elencherò alcuni.

+0

1) ma all'interno di threadProc c'è un ciclo while, quindi il thread sarà sempre occupato? In che modo NSRunLoop può impedirgli di eseguirlo? 2) AFAIK, questo è un meccanismo per garantire che molte chiamate a performSelector: onThread: trasferirà il lavoro a questo stesso thread di lavoro, giusto? – onmyway133

+0

1) scusa per non essere chiaro: il sistema operativo sospenderà il thread all'interno di runMode: se non c'è nulla da elaborare per il codice. 2) è una caratteristica del sistema - ma ce ne sono altre - elaborazione di port e timer. Imparerai di più leggendo i documenti Apple su CFRunloop - credo ci sia una guida su di esso. –