提问人:Active Hub 提问时间:8/5/2023 更新时间:8/7/2023 访问量:42
当管道有信息时,不调用可读过程
Readable procedure not getting called when pipe has info
问:
在 linux 上,我使用“mkfifo pip”创建了一个管道文件。在一个终端上,我发出“tail -f pip”,在另一个终端上,我发出“ls > pip”。我可以看到从第二个终端到第一个终端的信息流。
我创建了一个 TCL 脚本来读取流入点的信息。
fconfigure stdout -buffering none
set fd [open "pip"]
fconfigure $fd -blocking 0 -buffering line
fileevent $fd readable [list Treading $fd]
proc Treading {desc} {
gets $desc line
puts stdout "Got line - $line"
}
while {1} {
puts "waiting..."
after 2000
}
我运行了该程序并从另一个终端发出“cat > pip”,在输出中我没有看到任何从 Treading 过程调用的“Got line”打印。
$tclsh sockpip.tcl
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
如果我遗漏了什么,有人可以帮我澄清一下吗?我想让事件驱动的编程工作。
提前致谢。 紫外线。
答:
2赞
Colin Macleod
8/5/2023
#1
要触发事件,您需要使用非阻塞形式 ,请参阅 https://www.tcl-lang.org/man/tcl8.6/TclCmd/after.htm#M6,并且需要启动 Tcl 事件循环。而不是:readable
after
while {1} {
puts "waiting..."
after 2000
}
尝试:
proc waiting {} {
puts "waiting..."
after 2000 waiting
}
waiting
vwait forever
2赞
Donal Fellows
8/7/2023
#2
关键问题是你正在使用一个阻塞。Tcl 解释器是严格的单线程解释器,并且仅在您调用 or(或在 Tcl 的 C API 中包装这些或调用的其他东西)时才提供事件循环。不建议以递归方式调用它们,因为您可能会因可重入回调而陷入混乱,而您不希望这样。after
vwait
update
Tcl_DoOneEvent()
但是,您可以使用协程和非阻塞来执行循环,如下所示:after
proc snooze {delay} {
after $delay [info coroutine]
yield
}
coroutine MyWaitLoop apply {{} {
while {1} {
puts "waiting..."
snooze 2000
}
}}
vwait forever; # Run the event loop until you stop it
由于这是在事件循环中等待,因此将调用管道的处理程序。
评论