Eri*_*son 2 events multithreading tcl
我有一个带有多个I/O接口的系统,我正在将所有这些接口的输出收集到一个公共日志中.其中两个接口是通过行为良好的通道打开的,这些通道作为类文件对象打开,并且可以在事件基础上使用"fileevent readable"进行管理.另外两个是问题.
这些是供应商提供的库,其他人已经将其包含在Tcl包中(snoopy,FWIW).但是,唯一的读取访问是阻塞调用,并且程序包中没有任何内容会导致事件等同于fileevent.
我已经弄清楚如何生成一个单独的线程来阻止读取,拉出结果,并将其放入主线程的消息队列中.但是在读取队列时使用主线程块似乎会破坏目的,特别是因为它必须阻塞两个队列.而且我无法让读者生成一个可以触发主线程来读取队列的事件.
到目前为止,我已经查看了tcl.tk wiki无济于事.我已经尝试使用uevent库在消息推送上生成一个事件,但事件转到写入线程而不是读取线程,这实际上没有帮助.似乎应该有一些与Thread条件变量相关的解决方案,但到目前为止,我还没有找到适合该库使用的设计模式.
如果所有其他方法都失败了,我将回到Tk事件,但我试图让Tk脱离这个,因为它意味着是一个没有GUI的自动化系统,任何提及Tk都会将tclsh推入愿望并弹出一个GUI窗口.
我觉得我很亲密,但只是缺少一些东西.
首先,主线程需要运行事件循环才能接收事件.执行此操作的惯用方法是vwait forever在完成程序设置后使用(我假设您不会写入该变量)但是如果您运行Tk,则您已经有一个事件循环(GUI 需要事件循环) .
有两种方法可以在线程之间进行消息传递.
该thread::send命令使用事件来调度代码以在线程之间执行(消息).您需要做的就是告诉工作线程主线程的ID是什么,因此它知道要发送到哪里.请注意,您可能希望异步发送事件,如下所示:
thread::send -async $mainID [list eventReceiver "something happened" $payload]
Run Code Online (Sandbox Code Playgroud)
如果您使用的是Tcl 8.6,则可以使用它chan pipe来创建未命名的OS管道.然后,您可以使用普通的文件事件等,以此方式将信息从线程传递到另一个.
# In master
lassign [chan pipe] readSide writeSide
thread::transfer $worker $readSide
thread::send $worker [list variable pipe $readSide]
fconfigure $writeSide -blocking 0
fileevent $writeSide readable [list handleLine $writeSide]
# In worker
fconfigure $pipe -blocking 0 -buffering line
puts $pipe "got event: $payload"
Run Code Online (Sandbox Code Playgroud)
回想起来,使用线程事件可能更容易!(管道的主要优点是,如果需要,您还可以将工作人员置于另一个进程中.)