¿Por qué no funciona mi NSLock?

Estoy escribiendo un código para representar y rotar una image cuyos detalles se calculan y actualizan simultáneamente. Funciona sin errores en un solo hilo (con un enlace de visualización), pero se ve torpe, y no quiero que los cálculos se activen mediante el enlace de visualización. Entonces, quiero ejecutar todo el código relacionado con OpenGL en el hilo principal (con el enlace de visualización) y todos los cálculos en un segundo hilo (ejecutando un bucle de time (SÍ)).

Implementé esto usando NSThread. Funciona muy bien durante un time y luego falla con 'Hilo 1: Señal recibida del progtwig: "EXC_BAD_ACCESS"' durante glDrawArrays, y en ocasiones tiene extraños flashes de charts. Esto es lo que esperaba si el hilo principal lee los datos del nivel del model al mismo time que el segundo hilo lo sobrescribía.

Luego definí un NSLock en el object model y lo bloqueé para todos los types de escritura (en mi class de model) y para la lectura (en mi class de vista) … pero puede generar el mismo error, y los charts aún ocasionalmente tienen destellos extraños .

¿He hecho algo mal aquí o es mi problema en otro lado?

En segundo lugar, ¿cuál es la forma correcta de detener el segundo hilo en este caso? La reference de la class NSThread sugiere usar cancelar, verificar se cancela y salir si es así, pero también dice que debe evitarse la salida de invocación.

Aquí están las modificaciones al código: en mi class de controller (estoy usando XCode 4.2 con ARC; todos mis ivars no son atómicos):

@interface MyController : NSObject { NSThread *calcThread; ... } // (I do not give it an @property or @synthesize line) @implementation MyController - (void) awakeFromNib { calcThread = [[NSThread alloc] initWithTarget:self selector:@selector(calcLoop:) object:nil]; [calcThread start]; ... } - (void) calcLoop:(id)arg { @autoreleasepool { while (YES) [myModel calculate]; } } ... 

Puse el NSLock en mi class de model:

 @interface MyModel : NSObject { NSLock* oLock; ... } @property (nonatomic, strong) NSLock* oLock; @implementation myModel -(id) init { oLock = [[NSLock alloc] init]; ... } -(void) changeModelAppearance { [oLock lock]; ... [oLock unlock]; } ... 

y en mi class de vista:

 @implementation MyView -(void) modelUpdated:(NSNotification *) notification { // modelUpdated is called via the NSNotificationCenter MyModel* myModel = (MyModel*) [notification object]; [myModel.oLock lock]; ... // update OpenGL structures with data from myModel [myModel.oLock unlock]; } ... 

¡Gracias!

Creo que en este caso sería mucho más fácil usar el envío gran central.

 @interface MyController : NSObject { // Not use why you're not inheriting from NSController here. dispatch_queue_t calQueue; ... } - (void) awakeFromNib { calcQueue = dispatch_queue_create("com.yourApp.calc", DISPATCH_QUEUE_SERIAL); dispatch_async(calcQueue, ^{ while(YES) // This will peg the CPU at 100% [myModel calculate]; }); } 

class de model

 @interface MyModel : NSObject { dispatch_queue_t modelQueue; ... } @property dispatch_queue_t modelQueue; @implementation myModel -(id) init { modelQueue = dispatch_queue_create("com.yourApp.model", DISPATCH_QUEUE_SERIAL); } -(void) dealloc { dispatch_release(modelQueue); } -(void) changeModelAppearance { dispatch_async(modelQueue, ^{ ... }); } ... 

Ver

 @implementation MyView -(void) modelUpdated:(NSNotification *) notification { // modelUpdated is called via the NSNotificationCenter MyModel* myModel = (MyModel*) [notification object]; dispatch_async(model.modelQueue, ^{ ... // update OpenGL structures with data from myModel }); } ... 

Para poner en pausa cualquiera de las queues, simplemente llama a dispatch_suspend y para reiniciar cualquier queue utiliza dispatch_resume

Si usa un timer en lugar de un bucle infinito, puede networkingucir la cantidad de CPU que está utilizando.

 calcTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); dispatch_source_set_timer(calcTimer, DISPATCH_TIME_NOW, DT, 1000); dispatch_source_set_event_handler(calcTimer, ^{ ... }); dispatch_resume(calcTimer); 

Esto usaría una sobrecarga de CPU mucho más baja.