2013-02-19 7 views
2

제공된 코드를 http://playground.arduino.cc/Interfacing/Cocoa (IOKit/ioctl 메서드)에 따라 Arduino에서 코코아 응용 프로그램으로 데이터를 보내려면 직렬 통신 예제를 실행하려고합니다. 그것은 작동하지만, 일단 시작 수신기 스레드를 멈출 수 없습니다.코코아 백그라운드 스레드에서 직렬 통신을 닫는 방법

내가 스위치 버튼 시작 시간에 시리얼 포트를 열고 수신기 스레드 실행 (시작/정지) 구현했습니다

:

- (IBAction) startButton: (NSButton *) btn { 
(…) 
error = [self openSerialPort: [SelectPort titleOfSelectedItem] baud:[Baud intValue]]; 
(…) 
[self refreshSerialList:[SelectPort titleOfSelectedItem]]; 
[self performSelectorInBackground:@selector(incomingTextUpdateThread:) withObject:[NSThread currentThread]]; 
(…) 
} 

스레드 코드, 실질적으로 예에서와 동일 제외를 내가받은 버퍼에서 직렬 패킷을 재건하고 SQLite 데이터베이스에 저장하는 코드를 포함했다고 :이 코드는 startButton 선택의도 부분 메인 스레드에서 포트를 닫으려고

- (void)incomingTextUpdateThread: (NSThread *) parentThread { 

// mark that the thread is 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 during read 

(…) 

// assign a high priority to this thread 
[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 = (int) read(serialFileDescriptor, byte_buffer, BUFFER_SIZE); // read up to the size of the buffer 
    if(numBytes>0) { 
     // format serial data into packets, but first append at start the end of last read 
     buffer = [[NSMutableString alloc] initWithBytes:byte_buffer length:numBytes encoding:NSASCIIStringEncoding]; 
     if (status == 1 && [ipacket length] != 0) { 
      [buffer insertString:ipacket atIndex:0]; 
      numBytes = (int) [buffer length]; 
     } 
     ipacket = [self processSerialData:buffer length:numBytes]; // Recompose data and save to database. 
    } 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; 

} 

, 제공된 예를 따르면 다음과 같습니다 :

if (serialFileDescriptor != -1) { 
    [self appendToIncomingText:@"Trying to close the serial port...\n"]; 
    close(serialFileDescriptor); 
    serialFileDescriptor = -1; 

    // Revisar... crec que el thread no s'adona que s'ha tancat el file descriptor... 
    // wait for the reading thread to die 
    while(readThreadRunning); 
    // re-opening the same port REALLY fast will fail spectacularly... better to sleep a sec 
    sleep(0.5); 

    //[btn setTitle:@"Start"]; 
    [Start setTitle:@"Start"]; 
} 

그러나 수신자 스레드가 전역 변수 serialFileDescriptor의 상태 변화를 인식하지 못하는 것으로 보입니다.

+0

사람이 읽을 수있는 일반 텍스트 나 바이너리 데이터를 보낼 수 있습니까? NSString과 그 자손은 전자의 경우에만 사용해야합니다. 후자를 읽고 있다면 NSMutableData를 사용해야한다. –

+0

또한,'buffer' /'ipacket' 댄스가 내가하는 일을하기위한 것이라는 가정하에, 그렇게하는 것이 훨씬 더 효율적인 방법이 있습니다. 'appendString :'또는'appendData :'를보십시오. –

답변

0

따라서 startButton:은 포트를 열고 스레드에서 읽기를 시작한 다음 즉시 포트를 닫습니다. 그것은 잘 돌아 가지 않을 것입니다.

startButton: 포트를 닫지 마십시오. 읽기 스레드가 완료되면 수행 할 작업을 남겨두고 다른 이유로 (예 : 종료) 포트를 닫아야하는 경우에만 주 스레드에서 수행하십시오.

정의 전역 변수는 프로그램 전체에서 볼 수 있으며 여기에는 스레드 경계가 포함됩니다. readThreadRunningFALSE으로 설정되지 않으면 (FALSE이 이국적인 것으로 정의되지 않은 것으로 가정 함) 읽은 스레드의 루프가 계속 실행 중이어야합니다. 여전히 데이터를 읽거나 read이 차단되었습니다 (더 많은 데이터를 기다리고 있습니다).

read에는 더 많은 데이터가 있는지 여부를 알 수있는 방법이 없습니다. 코드에있는 귀하의 의견에 의하면, 데이터가 있거나 포트가 닫힐 때까지 차단됩니다. 미리 읽어야 할 데이터의 양을 미리 알고, 그만큼 읽었을 때 멈추거나 모든 것이 전송 된 반대편 포트를 닫을 수 있는지 확인하는 방법을 찾아야합니다. 받았습니다.

관련 문제