在串行端口上使用read()操作取消线程

时间:2011-08-27 22:52:38

标签: objective-c c multithreading serial-port

在我的Cocoa项目中,我与连接到串口的设备进行通信。现在,我正在等待串行设备发送一些字节的特定消息。对于读取操作(以及一旦收到所需消息的反应),我创建了一个新线程。根据用户请求,我希望能够取消该帖子。

正如Apple在docs中建议的那样,我在线程字典中添加了一个标志,定期检查标志是否已设置,如果是,请调用[NSThread exit]。这很好。

现在,线程可能会卡住,等待串行设备最终发送12字节消息。读取调用如下所示:

numBytes = read(fileDescriptor, buffer, 12);

一旦线程开始从设备读取,但没有数据进入,我可以设置标志告诉线程完成,但线程不会读取标志,除非它最终收到至少12个字节的数据并继续处理。

有没有办法杀死当前在串行设备上执行读操作的线程?

编辑以澄清: 我不坚持为串行设备的I / O操作创建一个单独的线程。如果有办法封装操作,以便我能够在用户按下取消按钮时“杀死”它们,我非常高兴。 我正在为桌面Mac OS X开发Cocoa应用程序,因此不适用于移动设备及其功能的限制。 如果没有要读取的字节,解决方法是立即返回读取函数。我怎么能这样做?

2 个答案:

答案 0 :(得分:2)

使用selectpoll超时检测描述符何时可以读取。

将超时设置为(比方说)半秒并在循环中调用它,同时检查您的线程是否应该退出。

异步线程取消几乎总是一个坏主意。尽量坚持使用事件驱动的接口(如果需要,还要超时)。

答案 1 :(得分:1)

这正是pthread_cancel接口的设计目标。您需要在readpthread_cleanup_push中使用pthread_cleanup_pop打包该块,以便在线程被取消时可以安全地清理,并禁用取消(使用pthread_setcancelstate在此线程中运行的其他代码中,您不希望对其进行取消。如果适当的清理涉及多个调用框架,这可能会很痛苦;它本质上迫使你在每个调用级别使用pthread_cleanup_push并使用try / catch样式异常处理来构造线程代码,如C ++或Java。

另一种方法是为没有SIGUSR1标志的其他未使用信号(如SA_RESTART或其中一个实时信号)安装信号处理程序,以便它用{{中断系统调用1}}。信号处理程序本身可以是一个完整的无操作;唯一的目的是打断事情。然后,您可以使用EINTR中断特定线程中的pthread_kill(或任何其他系统调用)。这样做的好处是您不必将代码切换为使用C ++ / Java类型的习惯用法。您可以通过检查标志(指示线程是否被请求中止)来处理read错误,如果未设置标志则继续读取,或者返回导致调用者清理的错误代码并最终{ {1}}。

如果确实使用了中断信号处理程序,请确保所有可以返回EINTR的系统调用都包含在pthread_exit中重试(或检查中止标志并可选择重试)的循环中。否则事情就会严重破裂。