【问题标题】:error : can't read .... no such variable in TCL script using "after"错误:无法读取....在 TCL 脚本中使用“之后”没有这样的变量
【发布时间】:2015-03-25 08:24:31
【问题描述】:

我在工作场所的 TCL 自动化环境中工作。 我正在尝试使用“after”在我的脚本中运行延迟命令。 我遇到的问题是,当我尝试在“之后”下的代码块内指定带有变量的命令时,无法识别 var 并且我收到一条错误消息。 我将引用代码的相关部分。

proc test_script1 {{bh0 0} ...more vars....} {
.
.
.
after [expr 20000]   {
   set some_value[ ns1::probe_TCP_connections $bh0 $main_duration 1  15]    }

puts "the value i got is $some_value"
}

我似乎得到了一个错误: 无法读取“some_value”:没有这样的变量

任何人都可以建议问题是什么,以及如何解决它? 谢谢

【问题讨论】:

  • 你读过manual吗?您编写命令的方式使得after 的命令在继续执行脚本的同时以指定的延迟运行。所以puts "the value i got is $some_value" 在设置变量之前被执行。此外,after 块内的 set 看起来很可疑。
  • 你是对的,看跌期权是在之后执行的。我会澄清一下,假设我在看跌期权之前添加了一个延迟,还有另一个“之后”。解释器仍然无法识别变量
  • 另外,在手册中:“命令将在全局级别执行(在任何 Tcl 过程的上下文之外)”因此您必须从全局级别获取变量,并且有相当多的有几种方法可以做到这一点。
  • 首先感谢。如果您能详细说明,我将不胜感激。

标签: variables scope global-variables tcl


【解决方案1】:

您可以在apply 的帮助下捕获局部变量的值(建议使用list 来构建回调,即使它们变得非常重要)。由于apply 的主体是一个具有自己作用域的 lambda 表达式——一个无名的小过程——你必须在其中使用 global 来访问将持续存在的状态,并且在任何情况下都会从始终全局命名空间(因为该机制不知道如何在 异步 操作期间保留任意堆栈帧)。

after 20000 [list apply {{bh0 main_duration} {
    global some_value
    set some_value [ns1::probe_TCP_connections $bh0 $main_duration 1 15]
}} $bh0 $main_duration]

global some_value
vwait some_value
puts "The value was changed to $some_value"

有可能变得更加复杂,尤其是在 Tcl 8.6 中,它有一个协程系统,可以用来隐藏使用延续传递风格编程的复杂性。

【讨论】:

    【解决方案2】:

    这是一个proc,它将执行与您尝试执行的操作类似的操作:

    proc foo {} {
        # Make 'a' available to both the global scope and local scope
        global a
        # This is to check the current level
        puts "Current level: [info level]"
        # The command to be run in 500 ms, and I have added another check for the level
        after 500 {puts "Current level: [info level]"; set a 100}
        # Wait for further execution until the global variable 'a' changes
        vwait a
        # Prints a
        puts "Value of \$a: $a"
    }
    

    上面的输出将是:

    Current level: 1
    # After 500 ms, the below will print
    Current level: 0
    Value of $a: 100
    

    当您使用after 时,将在全局范围内创建变量a,除非显式授予访问权限,否则proc 无法访问该变量。最简单的方法之一是首先确保 proc 中的 a 可在全局和本地访问,global(级别 0)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-23
      • 2019-12-25
      • 1970-01-01
      • 2017-05-15
      • 2021-09-01
      相关资源
      最近更新 更多