2011-06-08 7 views
21

Así que estoy comenzando un nuevo NSThread que deseo poder usar más adelante llamando al performSelector:onThread:.... Por lo que entiendo es que llamar a los métodos agrega esa llamada al runloop en ese hilo, por lo que en su próxima iteración mostrará todas estas llamadas y luego las llamará hasta que no quede nada por llamar. Así que necesito este tipo de funcionalidad, un hilo inactivo listo para el trabajo que solo puedo invocar. Mi código actual es el siguiente:Mantenga NSThread vivo y ejecute NSRunLoop en él

- (void)doInitialize 
    { 
     mThread = [[NSThread alloc] initWithTarget:self selector:@selector(runThread) object:nil]; 
     [mthread start]; 
    } 

    - (void)runThread 
    { 
     NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init]; 

     // From what I understand from the Google machine is that this call should start the 
     // runloop on this thread, but it DOESN'T. The thread dies and is un-callable 
     [[NSRunLoop currentRunLoop] run]; 

     [pool drain]; 
    } 

    - (void)scheduleSomethingOnThread 
    { 
     [self performSelector:@selector(hardWork) onThread:mThread withObject:nil waitUntilDone:NO]; 
    } 

Pero el hilo no se mantiene viva, y la performSelector: onThread no hace nada. ¿Cómo hago esto de la manera correcta?

Respuesta

15

Un bucle de ejecución requiere al menos una "fuente de entrada" para ejecutarse. El ciclo de ejecución principal sí lo hace, pero debe agregar una fuente manualmente para obtener el método -run de un ciclo de ejecución secundario para hacer cualquier cosa. Hay un poco de documentación en este here.

Una forma ingenua de hacer que esto funcione sería simplemente poner [[NSRunLoop currentRunLoop] run] en un ciclo infinito; cuando hay algo que hacer, lo hará y, de lo contrario, regresará de inmediato. El problema es que el hilo tardará una cantidad decente de tiempo de procesador simplemente esperando que ocurra algo.

Otra solución es instalar un NSTimer en este ciclo de ejecución para mantenerlo activo.

Pero, si es posible, debe utilizar un mecanismo diseñado para este tipo de cosas. Si es posible, puede usar NSOperationQueue para operaciones en segundo plano.

+0

Gracias, que es un poco más claro ahora. – ErikPerik

+4

Esto también es cierto para el ciclo de ejecución principal en una herramienta de línea de comandos. Es una aplicación NS/UIA que proporciona las fuentes de entrada predeterminadas en el ciclo de ejecución principal en una aplicación GUI. –

8

este pedazo de código debe forzar el hilo que esperar para siempre

BOOL shouldKeepRunning = YES;  // global 
NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; 
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; // adding some input source, that is required for runLoop to runing 
while (shouldKeepRunning && [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]); // starting infinite loop which can be stopped by changing the shouldKeepRunning's value 
Cuestiones relacionadas