我是Tcl的初学者。我正在尝试学习Tcl,而又不参与Tk。我遇到了类似这样的命令vwait
,after
但是由于大多数解释都涉及event loop
Tk的概念,并且使我更加困惑,因此我感到困惑。我想了解事件和事件循环的概念,以及我提到的命令与它们之间的关系,请为此提供一些参考。外植体不应该以Tk为例,不使用Tcl扩展名,不具备事件先验知识。tcl事件循环的某些(最小)玩具示例和实际wordl应用程序,不包括GUI编程/ Tk,将不胜感激。
我在Tclers Wiki上遇到了本教程。我正在寻找其他类似的参考或解释。
如果不使用Tk,则使用事件循环的主要原因是在执行其他一些I / O绑定任务时在后台等待,以及处理服务器套接字。
让我们看一下服务器套接字。
当您使用以下方法打开服务器套接字时:
socket -server myCallbackProcedure 12345
您正在安排在服务器套接字上设置事件处理程序,以便在有传入连接时,该连接将转换为您的普通套接字,并调用您提供的回调过程(myCallbackProcedure
)来处理与套接字的交互。通常,这通常是通过设置fileevent
处理程序来完成的,以便在传入数据到达时对其进行处理,而不是阻塞等待它的进程,但这不是必须的。
事件循环?这是一段代码在调用操作系统(通过select()
,poll()
,WaitForMultipleObject()
,等,这取决于操作系统和编译选项)要等到事情发生在任何指定的通道或发生超时。这非常有效,因为可以在等待时挂起进行调用的线程。如果发生某种情况,则OS调用返回,并且Tcl安排要调用的相关回调。(内部有一个队列。)这是一个循环,因为一旦处理了事件,通常回去等待一些事件。(这是Tk所做的,直到没有更多可控制的窗口vwait
为止,并且直到某个事件处理程序设置了它正在等待的变量为止,该做什么。)
异步等待是使用按时间排序的队列进行管理的,并转换为在OS中设置呼叫超时。
一个例子:
socket -server myCallbackProcedure 12345
proc myCallbackProcedure {channel clientHost clientPort} {
puts "Connection from $clientHost"
puts $channel "Hi there!"
flush $channel
close $channel
}
vwait forever
# The “forever” is an idiom; it's just a variable that isn't used elsewhere
# and so is never set, and it indicates that we're going to run the process
# until we kill it manually.
异步连接处理的一个更复杂的示例,因此我们可以一次为多个连接提供服务(所需的CPU:最少):
socket -server myCallbackProcedure 12345
proc myCallbackProcedure {channel clientHost clientPort} {
puts "Connection from $clientHost"
fileevent $channel readable [list incoming $channel $clientHost]
fconfigure $channel -blocking 0 -buffering line
puts $channel "Hi there!"
}
proc incoming {channel host timeout} {
if {[gets $channel line] >= 0} {
puts $channel "You said '$line'"
} elseif {[eof $channel]} {
puts "$host has gone"
close $channel
}
}
vwait forever
甚至更复杂的示例将在连接上的最后一条消息之后10秒(= 10000ms)关闭连接:
socket -server myCallbackProcedure 12345
proc myCallbackProcedure {channel clientHost clientPort} {
global timeouts
puts "Connection from $clientHost"
set timeouts($channel) [after 10000 [list timeout $channel $clientHost]]
fileevent $channel readable [list incoming $channel $clientHost]
fconfigure $channel -blocking 0 -buffering line
puts $channel "Hi there!"
}
proc incoming {channel host timeout} {
global timeouts
after cancel $timeouts($channel)
if {[gets $channel line] >= 0} {
puts $channel "You said '$line'"
} elseif {[eof $channel]} {
puts "$host has gone"
close $channel
unset timeouts($channel)
return
}
# Reset the timeout
set timeouts($channel) [after 10000 [list timeout $channel $host]]
}
proc timeout {channel host} {
global timeouts
puts "Timeout for $host, closing anyway..."
close $channel
unset -nocomplain timeouts($channel)
}
vwait forever
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句