2013-02-19 74 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无法知道是否会有更多的数据。正如你在代码中所说的那样,它会阻塞,直到有一些数据返回或端口被关闭。您应该提前知道需要阅读多少数据,并且在阅读完这些内容后停止阅读,或者在发送完所有内容后查看是否可以关闭另一端的端口,以及接收。

相关问题