2011-02-06 2 views
9

몇 초 후에 NSPanel을 닫으려고하는데 NSTimer를 시작할 수 없습니다. 화재 메서드를 명시 적으로 호출하면 화재가 발생하지만 결코 실행되지 않습니다. 내 코드는 다음과 같습니다.NSTimer가 시작되지 않습니다

- (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]; 
} 

나는 내 코드에 스레딩이 있습니다. 이게 내 타이머를 엉망으로 만든다고 생각해. 에 의해 다른 방법에서 호출

-(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]; 
} 

: [self performSelectorInBackground:@selector(incomingTextUpdateThread:) withObject:[NSThread currentThread]];

+0

음 ... 잘못된 것이 없지만 currentThread를 withObject : 매개 변수로 전달하는 이유는 무엇입니까? 당신은 그 방법에서 그것을 사용하는 것처럼 보이지 않습니다. 왜 그냥 nil을 넘기지 않을까요? – jakev

+7

내가 뭘 의심하는지 (그냥 의심 스러운데, startRemoveProgressTimer를 호출하는 것을 볼 수 없기 때문에 :) scheduledTimerWithTimeInterval은 주 스레드의 루프가 아닌 현재 스레드의 실행 루프에 타이머를 추가합니다. 실행 루프를 사용하지 않는 백그라운드 스레드에서 타이머를 작성하는 경우 - 파일 디스크립터에서 while (1) 루프를 읽고 돌면, 실행 루프는 결코 처리 할 기회를 갖지 않습니다 모든 지연 타이머. 명시 적으로 주 스레드의 실행 루프에 추가하고 결과를 확인하십시오. – rgeorge

+0

startRemoveProgressTimer :가 NSNotification에 묶여 있다고 말하면 차이가 있습니까? 왜 내가 현재 스레드에서 전달 오전으로, 나는 잘 모르겠다. 내 응용 프로그램에 다른 사람의 코드를 적용하려고합니다. 원래 코드는 다음과 같습니다. http://arduino.cc/playground/Interfacing/Cocoa하지만 (Snow) Leopard에서 컴파일하기 위해 수정해야만했으며, 내 자신의 논리 중 일부를 넣었습니다. –

답변

18

당신이 rgeorge 감사!

실행 루프에 타이머를 추가하면 수동으로 작동합니다!

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

특히, * main * (메인 쓰레드) 실행 루프에 추가하십시오. 'scheduledTimer ...'메소드는 실행 루프에 타이머를 추가하지만 현재의 (현재 스레드의) 실행 루프에 타이머를 추가합니다. 또한 메인 쓰레드 수행을 위해 타이머를 생성/스케줄함으로써 응답 할 수도 있습니다. –

관련 문제