行者的学习博客

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

http://blog.csdn.net/dulixin/archive/2008/05/04/2383555.aspx

1、after

after主要用于要延迟一段时间再执行脚本,update主要用于处理挂起的事件和回调,vwait可以跟踪一个变量的修改。

名称
after - 等待一段时间后再执行命令

语法
after ms
after ms ?script script script ...?
after cancel id
after cancel script script script ...
after idle ?script script script ...?
after info ?id?


描述
这个命令用来延迟程序执行或者在后台执行命令,它有几种形式,取决于这个命令的第一个参数:

after ms
Ms必须是个整型数据,以毫秒为单位。这个命令是休眠ms毫秒后返回。当这个命令在休眠的时候应用程序不想赢任何事件。
after ms ?script script script ...?
这种形式的命令直接返回数值,但是会在ms毫秒后把一个Tcl命令作为事件处理来运行。这个命令在给出的时候就会被立刻执行.延迟命令就像concat命令格式的风格被连接起来,这个命令将在全局运行(脱离所有Tcl进程的上下文)。当运行延迟命令时产生错误就使用interp bgerror机制来报告错误。after命令返回一个可以使用after cancel来取消延迟命令的ID。
after cancel id
取消运行之前已经确定要运行的延迟命令。id指出了哪个延迟命令会被取消,之前必须有一个after命令返回的id。如果给出id的命令已经运行那么after cancel就没有作用。
after cancel script script ...
这个命令也可以取消一个延迟命令的执行,这个script参数被使用空格分隔连接在一起(就像concat命令的风格),如果有一个没有执行的命令和要取消的命令相同,这个命令就被取消运行,如果没有和要取消命令相同的命令那么after cancel就没有作用.
after idle script ?script script ...?
把script参数使用空格分隔连接在一起(就像concat命令的风格),并且当空闲回调后安排最终的脚本稍后会被执行。这个脚本会立刻运行,接着会进入事件循环而且进程中没有事件。这个命令返回一个可以使用after cancel取消的延迟命令ID。当运行延迟命令时产生错误就使用interp bgerror机制来报告错误。
after info ?id?
这个命令返回当前存在的事件句柄。如果没有id参数没有提供,这个命令返回所有被after命令创建的事件句柄。如果提供了id,指定一个存在的句柄,这个句柄必须是之前使用after命令返回的参数而且必须不能已经触发或者取消。这个命令返回一个包含两个元素的列表,第一个元素是命令相关的id,第二个元素指示事件句柄类型是idle还是timer。
after ms和after idle形式的命令假定应用程序是事件驱动的,直到应用程序进入了事件循环,延迟命令才会被执行.在不是一般事件驱动的应用程序当中,比如tclsh,可以使用vwait或者update命令进入事件循环.

示例
这个例子定义了一个命令使tcl空闲N秒:

proc sleep {N} {   after [expr {int($N * 1000)}]}
下面的脚本使wake_up在8个小时后运行(在这个时间事件循环被激活):

after [expr {1000 * 60 * 60 * 8}] wake_up
下面的命令可以被用于一步一步地方式做长时间运行的计算(就像这里描述的::my_calc::one_step,假设返回一个布尔数值来标志其它的步骤是否在执行).既然计算本身需要被排序所以可以逐步工作.这个技巧在使用的时候需要十分小心,需要避免事件循环杯进程管理给饿死(当下一个步骤去做一个已经触发的时间事件时正好事件队列被耗尽),在你做一个很慢的任务时,想确认一个TK GUI是否还有响应的时候非常有用.

proc doOneStep {} {   if {[::my_calc::one_step]} {      after idle [list after 0 doOneStep]   }}doOneStep

after有几种形式,使用比较灵活。
    最简单的形式,间隔一定时间后再运行脚本:
    % after 5000
    上面的命令就是间隔5秒钟后再继续运行脚本,这在等待其它设备处理时比较有效。
   
    间隔一段时间后执行一条命令:  
    % set a a
    a
    % after 5000 set a b
    after#1
    间隔5秒钟后执行命令set a b,如果等待5秒钟后再查看$a的值就变成b了。需要注意的是,在tcl中,时间循环并没有开启,而tk中事件循环总是活动的,所以在tcl脚本中使用时需要非常小心,可能你需要的值在5秒钟后并没有改变,这里就需要使用到两个命令update和vwait,update命令可以时解释器去处理挂起的事件,vwait可以等待一个变量到修改为止,下面举例说明:
    如果在5秒钟之后使用查看变量a里面的值:
    % puts $a
    a
    还是a,并没有修改为b,那么这个时候使用update:
    % update
    % puts $a
    b
    上面的方法可能在实际使用时并没有意义,也许脚本的编写者是想在tcl中精确的控制脚本的执行时间,那也没有问题,可以使用vwait来操作,在时间间隔的期限内使用vwait可以使命令在精确的时间间隔时执行:
    % set a a
    a
    % after 5000 set a b
    after#1
    % vwait a
    %
    会等待到第5秒钟执行赋值命令。
 
 
    如果注册了一条命令在某个时间执行,也可以取消这个命令的执行,使用after cancel命令,这个命令有两种形式,既可以输入要取消命令的ID,也可以使用该命令本身来取消。
    如想要取消ID为after#1的命令:
    % after cancel after#1
    如果ID为after#1的命令存在就去掉这个命令的注册,如果不存在就什么都不发生。
    取消一个命令体:
    % after 5000 set a c
    after#2   
    % after cancel set a c
    以上命令就会取消set a c的事件注册,如果不存在这个命令就什么都不发生。
 
    显示目前注册的after事件或者某个after事件的详细信息:
    直接使用after info命令来显示所有的after事件:
    % after 5000 set a b
    after#1
    % after 5000 set a c
    after#2
    % after info
    after#2 after#1
    如果需要知道after事件的详细信息,就需要使用具体的事件ID:
    % after info after#1
    {set a b} timer

2、update

名称
update - 处理挂起的事件和空闲回调

语法
update ?idletasks?


描述
这个命令用来给应用程序“更新”,进入事件循环直到所有挂起的事件和空闲回调都执行完毕。

如果指定idletasks,就不处理新的事件或错误,只有空闲回调被调用,这就导致操作被延迟了,就像显示更新和窗口设计,会被立刻执行。

当应用程序的状态发生变化和需要这些变化立刻显示时update idletasks命令是非常有用的,不用等待到脚本完成。多数显示更新被当作空闲回调来执行,所以update idletasks可以使它们运行。但是这里有一些更新只能在事件响应中发生,像窗口尺寸变化触发等,这些更新不会在update idletasks中发生。

当运行一个长的运算但是仍然想和应用程序交互时,update命令在脚本中非常有用。

示例
运行一个循环约一秒钟后停止:

set x 1000

set done 0

after 1000

set done 1

while {!$done} {  

  #一个无聊的例子   

set x [expr {log($x) ** 2.8}]

#测试时间是否到   

update

}

3、vwait

名称
vwait - 一直等待直到一个变量被修改为止

语法
vwait varName


描述
这个命令进入Tcl事件循环,Tcl将会一直处理事件直到变量varName被修改为止,一旦varName被修改了,vwait命令将会立刻返回,varName必须是一个全局范围变量。(要么是一个全局变量,要么带有完全的名字空间路径)。

在一些情况下在varName被修改后vwait命令可能不会立刻返回,如果设置varName的事件句柄没有完成,那么vwait命令就不会立刻返回。例如,如果一个事件句柄设置varName,然后它自己调用vwait去等待一个不同的变量,这样的话有可能需要经过长时间后才能返回。在这种情况下最高堆栈层的vwait命令阻塞,等待事件句柄完成,所以不能返回。

示例
运行事件循环直到一些事件调用exit。

vwait forever
在连接一个服务器套接字时等待5秒钟,否则关闭套接字继续运行脚本。

# Initialise the stateafter 5000 set state timeoutset server [socket -server accept 12345]proc accept {args} {   global state connectionInfo   set state accepted   set connectionInfo $args}

# Wait for something to happenvwait state

# Clean up events that could have happenedclose $serverafter cancel set state timeout

# Do something based on how the vwait finished...switch $state {   timeout {      puts "no connection on port 12345"   }   accepted {      puts "connection: $connectionInfo"      puts [lindex $connectionInfo 0] "Hello there!"   }}

posted on 2009-07-30 17:56  ylclass  阅读(6945)  评论(0编辑  收藏  举报