2011-02-06 11 views
9

Estoy tratando de cerrar un NSPanel después de un par de segundos de retraso, pero no puedo hacer que mi NSTimer comience. Se disparará si invoco explícitamente el método de fuego en él, pero nunca irá solo. Aquí está mi código:NSTimer nunca comienza

- (void)startRemoveProgressTimer:(NSNotification *)notification { 
    NSLog(@"timer should start"); 
    timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(removeProgress:) userInfo:nil repeats:NO]; 
} 

- (void)removeProgress:(NSTimer *)timer { 
    [progressPanel close]; 
} 

Tengo algunos hilos en mi código como tal. Supongo que esto es lo que está estropeando mi temporizador.

-(void)incomingTextUpdateThread:(NSThread*)parentThread { 
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

//mark the thread as running 
readThreadRunning = TRUE; 

const int BUFFER_SIZE = 100; 
char byte_buffer[BUFFER_SIZE]; //buffer for holding incoming data 
int numBytes = 0; //number of bytes read 
NSString *text; //incoming text from the serial port 

[NSThread setThreadPriority:1.0]; 

//this will loop until the serial port closes 
while (TRUE) { 
    //read() blocks until some data is available or the port is closed 
    numBytes = read(serialFileDescriptor, byte_buffer, BUFFER_SIZE); 
    if(numBytes > 0) { 
     //creat a string from the incoming bytes 
     text = [[[NSString alloc] initWithBytes:byte_buffer length:numBytes encoding:[NSString defaultCStringEncoding]] autorelease]; 
     if(!([text rangeOfString:SEND_NEXT_COORDINATE].location == NSNotFound)) { 
      //look for <next> to see if the next data should be sent 
      if(coordinateNum <[coordinatesArray count]) { 
       [self sendNextCoordinate]; //send coordinates 
      } 
      else { 
       [self writeString:FINISH_COORDINATES_TRANSMIT]; //send <end> to mark transmission as complete 
       NSNumber *total = [NSNumber numberWithUnsignedInteger:[coordinatesArray count]]; 
       NSDictionary *userInfo = [NSDictionary dictionaryWithObject:total forKey:@"progress"]; 
       [[NSNotificationCenter defaultCenter] postNotificationName:@"uploadProgressChange" object:self userInfo:userInfo]; //update progress bar to completed 
      } 


     } 

     [self performSelectorOnMainThread:@selector(appendToIncomingText:) withObject:text waitUntilDone:YES]; //write incoming text to NSTextView 
    } else { 
     break; //Stop the thread if there is an error 
    } 
} 

// make sure the serial port is closed 
if (serialFileDescriptor != -1) { 
    close(serialFileDescriptor); 
    serialFileDescriptor = -1; 
} 

// mark that the thread has quit 
readThreadRunning = FALSE; 

// give back the pool 
[pool release]; 
} 

¿Qué se llama desde otro método por: [self performSelectorInBackground:@selector(incomingTextUpdateThread:) withObject:[NSThread currentThread]];

+0

Hmm ... no veo nada mal, pero ¿por qué pasa el actualThread como el parámetro withObject:? Parece que no lo utilizas en ese método, ¿por qué no solo pasas nulo? – jakev

+7

Una sospecha que tengo (solo una sospecha, ya que no puedo ver qué llamadas startRemoveProgressTimer :) scheduledTimerWithTimeInterval agrega el temporizador al ciclo de ejecución del subproceso actual, no al del subproceso principal. Si está creando su temporizador en una secuencia de fondo que nunca usa su ciclo de ejecución, si solo se sienta y gira en un rato (1) leyendo un bucle desde un descriptor de archivo, digamos, el bucle de ejecución nunca tiene la oportunidad de tratar con cualquier temporizador en cola. Intente agregarlo explícitamente al bucle de ejecución del subproceso principal y vea qué sucede. – rgeorge

+0

¿Haría una diferencia si le dijera que startRemoveProgressTimer: está vinculado a una NSNotification? En cuanto a por qué estoy pasando el hilo actual, no estoy seguro. Estoy tratando de adaptar el código de otra persona a mi aplicación. El código original está aquí: http://arduino.cc/playground/Interfacing/Cocoa pero tuve que hacer algunas modificaciones para compilarlo en (Snow) Leopard, y puse algo de mi propia lógica. –

Respuesta

18

Gracias rgeorge !!

¡Agregar manualmente el temporizador al ciclo de ejecución lo hizo funcionar!

timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(removeProgress:) userInfo:nil repeats:NO]; 
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; 
+4

Específicamente, agregándolo al bucle de ejecución * main * (thread principal). Los métodos 'scheduledTimer ...' agregan el temporizador al ciclo de ejecución, pero lo agregan al ciclo de ejecución actual (del actual subproceso). También habría funcionado para realizar una ejecución de hilo principal a la que respondas al crear/programar el temporizador. –