我是Tcl的初学者。我正在尝试学习 Tcl 而不涉及 Tk。我遇到过像vwaitand这样的命令after,但我很困惑,因为大多数解释都涉及 的概念event loop,并且主要通过使用 Tk 进一步演示了这个概念。我想了解事件和事件循环的概念以及我提到的命令如何与它们相关,请参考我的一些参考资料。解释不应使用 Tk 作为示例,不使用 Tcl 扩展,假设没有事件的先验知识。除了 GUI 编程/Tk 之外,一些(最小的)玩具示例和 tcl 事件循环的实际应用将受到赞赏。
我在 Tclers wiki 上看到了这个教程。我正在寻找类似的其他参考或解释。
如果您不使用 Tk,那么使用事件循环的主要原因是在执行其他一些 I/O 密集型任务时在后台等待,以及处理服务器套接字。
\n\n让我们看看服务器套接字。
\n\n当您使用以下命令打开服务器套接字时:
\n\nsocket -server myCallbackProcedure 12345\nRun Code Online (Sandbox Code Playgroud)\n\n您正在安排在服务器套接字上设置一个事件处理程序,以便当有传入连接时,该连接将转换为普通套接字,并myCallbackProcedure调用您提供的回调过程 ( ) 来处理与套接字的交互。这通常是通过设置fileevent处理程序来完成的,以便传入的数据在到达时得到处理,而不是阻塞等待它的进程,但这不是必须的。
事件循环?这是一段调用操作系统(通过 、 、 等,具体取决于操作系统和构建选项)的代码select(),poll()以WaitForMultipleObject()等待任何指定通道上发生某些情况或发生超时。它非常高效,因为进行调用的线程可以在等待时挂起。如果发生某些情况,操作系统调用将返回,并且 Tcl 会安排调用相关回调。(内部有一个队列。)这是一个循环,因为一旦处理了事件,通常会返回并等待更多事件。(这就是 Tk 所做的事情,直到没有更多的窗口可供它控制,以及vwait直到它正在等待的变量被某个事件处理程序设置为止。)
异步等待使用按时间排序的队列进行管理,并转换为设置操作系统调用的超时。
\n\n一个例子:
\n\nsocket -server myCallbackProcedure 12345\nproc myCallbackProcedure {channel clientHost clientPort} {\n puts "Connection from $clientHost"\n puts $channel "Hi there!"\n flush $channel\n close $channel\n}\nvwait forever\n# The \xe2\x80\x9cforever\xe2\x80\x9d is an idiom; it\'s just a variable that isn\'t used elsewhere\n# and so is never set, and it indicates that we\'re going to run the process\n# until we kill it manually.\nRun Code Online (Sandbox Code Playgroud)\n\n一个稍微复杂一些的异步连接处理示例,因此我们可以一次提供多个连接(所需的 CPU 数量:最少):
\n\nsocket -server myCallbackProcedure 12345\nproc myCallbackProcedure {channel clientHost clientPort} {\n puts "Connection from $clientHost"\n fileevent $channel readable [list incoming $channel $clientHost]\n fconfigure $channel -blocking 0 -buffering line\n puts $channel "Hi there!"\n}\nproc incoming {channel host timeout} {\n if {[gets $channel line] >= 0} {\n puts $channel "You said \'$line\'"\n } elseif {[eof $channel]} {\n puts "$host has gone"\n close $channel\n }\n}\nvwait forever\nRun Code Online (Sandbox Code Playgroud)\n\n一个更复杂的示例,将在最后一条消息发送后 10 秒(= 10000 毫秒)关闭连接:
\n\nsocket -server myCallbackProcedure 12345\nproc myCallbackProcedure {channel clientHost clientPort} {\n global timeouts\n puts "Connection from $clientHost"\n set timeouts($channel) [after 10000 [list timeout $channel $clientHost]]\n fileevent $channel readable [list incoming $channel $clientHost]\n fconfigure $channel -blocking 0 -buffering line\n puts $channel "Hi there!"\n}\nproc incoming {channel host timeout} {\n global timeouts\n after cancel $timeouts($channel)\n if {[gets $channel line] >= 0} {\n puts $channel "You said \'$line\'"\n } elseif {[eof $channel]} {\n puts "$host has gone"\n close $channel\n unset timeouts($channel)\n return\n }\n # Reset the timeout\n set timeouts($channel) [after 10000 [list timeout $channel $host]]\n}\nproc timeout {channel host} {\n global timeouts\n puts "Timeout for $host, closing anyway..."\n close $channel\n unset -nocomplain timeouts($channel)\n}\nvwait forever\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1726 次 |
| 最近记录: |