2013-02-19 70 views
2

我試圖運行一個串行通信示例,以便將數據從Arduino發送到可提供的代碼http://playground.arduino.cc/Interfacing/Cocoa(IOKit/ioctl方法)中的可可應用程序。它可以工作,但是一旦啓動,我無法停止接收器線程。如何關閉可可後臺線程中的串行通信

我已經實現了一個開關按鈕(開始/停止),其在啓動時打開串行端口並啓動接收器線程:

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

線程代碼實際上是相同的如示例中,除了我所包含的代碼從接收緩衝區重建串行數據包並將其保存到一個SQLite數據庫:

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

} 

我嘗試關閉該端口在主線程中使用此代碼,也startButton選擇的一部分,遵循提供的示例:

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。 – 2013-02-19 20:39:24

+0

此外,假設你的'buffer' /'ipacket'舞蹈是爲了做我認爲正在做的事情,還有更有效的方法來做到這一點。看看'appendString:'或'appendData:'。 – 2013-02-19 20:46:04

回答

0

那麼,startButton:打開端口,產生一個線程開始讀取它,然後立即關閉端口?這不會很好。

startButton:不應關閉端口。當讀線程完成時,讓它保持這個狀態,並且只在需要關閉端口時出於某種其他原因(例如退出)纔在主線程上執行它。

根據定義,全局變量在整個程序中都是可見的,這包括跨越線程邊界。如果readThreadRunning沒有設置爲FALSE(假定FALSE還沒有被定義爲異國情調),那麼你的讀線程的循環必須仍在運行。要麼它仍在讀取數據,要麼阻止read(它正在等待更多數據)。

請注意,read無法知道是否會有更多的數據。正如你在代碼中所說的那樣,它會阻塞,直到有一些數據返回或端口被關閉。您應該提前知道需要閱讀多少數據,並且在閱讀完這些內容後停止閱讀,或者在發送完所有內容後查看是否可以關閉另一端的端口,以及接收。

相關問題