2011-02-06 101 views
9

我只是在幾秒鐘後關閉NSPanel,但我無法啓動我的NSTimer。如果我明確地調用它的fire方法,它會啓動,但它永遠不會自行完成。這裏是我的代碼: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:參數?你似乎沒有用這種方法,爲什麼不通過零? – 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 ...'方法將計時器添加到運行循環中,但將它添加到當前(當前線程)的運行循環中。它也可以通過創建/調度計時器來完成主線程執行。 –