2009-08-05 11 views

Respuesta

17

¿Desea que su hilo se detenga solo hasta que otro hilo le indique que se inicie de nuevo? Si es así, podría usar un NSConditionLock. Un NSConditionLock es similar a una variable de condición. Tiene un par de métodos básicos, lockWhenCondition, y unlockWithCondition, y lock. Un uso típico es tener el hilo de fondo en espera en el bloqueo de condición con "lockWhenCondition:" y el hilo en primer plano para establecer la condición, lo que hace que el hilo de fondo se active. La condición es un número entero simple, generalmente una enumeración.

He aquí un ejemplo:

enum { 
    kWorkTodo = 1, 
    kNoWorkTodo = 0 
} 

- (id)init { 
    if ((self = [super init])) { 
     theConditionLock = [[NSCoditionLock alloc] initWithCondition: kNoWorkTodo]; 
     workItems = [[NSMutableArray alloc] init]; 
    } 
} 

- (void)startDoingWork { 
    [NSThread detachNewThreadSelector:@selector(doBackgroundWork) toTarget:self withObject:nil]; 
} 

- (void)doBackgroundWork:(id)arg { 
    while (YES) { 
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
     NSArray *items = nil; 
     [theConditionLock lockWhenCondition:kWorkTodo]; // Wait until there is work to do 
     items = [NSArray arrayWithArray:workItems] 
     [workItems removeAllObjects]; 
     [theConditionLock unlockWithCondition:kNoWorkTodo]; 
     for(id item in items) { 
      // Do some work on item. 
     } 
     [pool drain]; 
    } 
} 

- (void)notifyBackgroundThreadAboutNewWork { 
    [theConditionLock lock]; 
    [workItems addObject:/* some unit of work */]; 
    [theConditionLock unlockWithCondition:kWorkTodo]; 
} 

En este ejemplo, cuando se llama startDoingWork doBackgroundWork: se iniciará en un subproceso en segundo plano, pero luego se detiene porque no hay ningún trabajo que hacer. Una vez que se invoca notifyBackgroundThreadAboutNewWork, doBackgroundWork: se iniciará y procesará el nuevo trabajo, y luego volverá a quedarse dormido a la espera de que haya nuevo trabajo disponible, lo que sucederá la próxima vez que se llame a notifyBackgroundThreadAboutNewWork.

+1

Muchas gracias por su solución. esto parece ser lo que necesito –

+0

Así que el proceso de coordinar hreads con NSlock, no tiene una latencia muy baja entre los hilos. Intenté utilizar los métodos de suspensión para NSthreada y fue realmente lento. –

+0

¿Podría decirme por qué trabaja antes y después de [theConditionLock unlockWithCondition: kNoWorkTodo]; también. cuál es la diferencia entre nslock y nsconditionlock –

0

No está claro lo que quiere hacer. Detener el hilo y reanudar la misma función en un nuevo hilo? (Eso sería inútil: ¿qué pasaba con el hilo viejo?) ¿Detener el hilo y reanudar la misma función en otro hilo existente?

De cualquier manera, no, no es posible, y ni siquiera es una buena idea. La solución correcta es dividir su función en dos, luego usar algunos o todos los ciclos de ejecución, NSTimer, performSelector… y NSPort para lograr lo que sea que desee hacer.

Su programa funcionará mucho mejor sin toda esta magia de hilo oscuro que está imaginando.

+1

no entiendes que quiero poder detener el hilo siempre que lo desee. Así que dividir la tarea sería inútil. –

+2

¿Por qué querrías hacer eso? Si quieres detener el trabajo que estás haciendo, hazlo. De lo contrario, es probable que detenga el hilo en el medio de algo, con esa cosa medio completa y mitad no. –

+1

¿Se da cuenta de que en lugar de ayudarme a seguir discutiendo? No sé cómo llegaste a 10k –

2

Si realmente tiene tareas que necesita ejecutar en un hilo de fondo, pero una tarea necesita que se complete otra antes de que se ejecute, recomendaría mirar NSOperation y NSOperationQueue. NSOperation admite la configuración de dependencias muy complejas, y NSOperationQueue gestionará la programación y ejecución de esas operaciones en todos los subprocesos de fondo que sean apropiados, en el orden correcto. El documentation de Apple en estos es bastante bueno, y Drew McCormack tiene un nice article sobre el tema en MacResearch.

Cuestiones relacionadas