如何在tcl 8.4中创建线程

如何在tcl 8.4中创建线程,tcl,Tcl,我是tcl的新手。我想在tcl中创建一个线程,它应该在后台不断调用自己 #!/usr/bin/env tclsh set serPort [open "/dev/ttyS0" RDWR] fconfigure $serPort -mode 115200,n,8,1 -blocking 0 while { 1 } { set data [gets $chan] puts $data } 我希望避免使用上述while循环,并为while循环中的功能创建一个可重复的线程。基本上,我是将

我是tcl的新手。我想在tcl中创建一个线程,它应该在后台不断调用自己

#!/usr/bin/env tclsh

set serPort [open "/dev/ttyS0" RDWR]

fconfigure $serPort  -mode 115200,n,8,1 -blocking 0 

while { 1 } {
set data [gets  $chan]
puts $data

}
我希望避免使用上述while循环,并为while循环中的功能创建一个可重复的线程。基本上,我是将电脑的COM1连接到一个设备,并从该设备获取串行数据。但如果端口上没有数据,即使我使用“eof”命令,它也不会从循环中出来。这就是我想要创建线程的原因


我计划使用Tcl_CreateThread来实现这一点,但我不知道如何使用它。相反,使用Tcl的惯用用法来处理非阻塞通道:为“通道可读”事件设置一个处理程序,并进入事件循环;当设备将数据发送到您打开的端口时,操作系统将数据传递给您的应用程序并调用回调

演示该概念的最小程序如下所示:

proc my_read_handler ch {
    set data [read $ch]
    if {[eof $ch]} {
        close $ch
        set ::forever done ;# this makes the call to `vwait` below to quit
        return
    }
    # Otherwise process the data here ...
}

set serPort [open "/dev/ttyS0" RDWR]

fconfigure $serPort -mode 115200,n,8,1 -blocking no
fileevent $serPort readable [list my_read_handler $serPort]

vwait ::forever ;# the program enters the event loop here
阅读更多关于这方面的内容

若干意见:

  • EOF仅在远程侧关闭时发生。如果在频道上调用
    close
    ,在这种情况下甚至不会调用“readable”
  • 如果您正在编写一个Tk应用程序,它将已经有一个事件循环,因此不需要调用
    vwait
    (此外,强烈建议他们不要这样做,因为这样会重新进入事件循环):您只需打开设备,比方说,在一个当用户单击按钮时执行的代码中,在获取的通道上设置可读回调,然后在该回调中执行其余处理(如上所示)

有关面向事件编程的更多信息,请阅读(及其链接)。还有维基——它包含了大量的例子和背景知识。

谢谢你的回复。但是上面的代码也给了我同样的问题,即使串行端口上没有数据,它也不会从事件循环中出来并继续搜索事件。如果我有一些其他事件要处理,当串行端口上没有数据时可能会发生。简而言之,上述两个代码都会阻塞我的系统,不允许执行任何操作。你能理解我在这里的意思吗。如果是,请帮助我,我不明白你的意思。使用事件循环可以让您完全忘记繁忙地等待数据:您设置了一个在数据可用时调用的命令前缀。您可以在任何给定时间在任何数量的通道上安装任意数量的回调。他们彼此不干涉。请注意,没有“搜索事件”这样的事情。基本上,当您调用
vwait
时,您的代码有效地进入睡眠状态,并且只有在注册回调的事件发生时才会被唤醒,从而执行回调。