某些命令在 TCL 线程内不起作用
Some commands are not working inside TCL thread
set t6 [thread::create] ; thread::send -async $t6 "set i1 0"
工作正常,没有任何错误。
set t5 [thread::create] ; thread::send -async $t5 "date"
但这是错误的:
执行“date”时命令名称“date”无效
可能是什么原因?
date
“命令”实际上不是命令。这是另一个程序,/bin/date
(或 /usr/bin/date
,具体取决于您的系统设置方式)。或者,在 Windows 上它是 CMD.EXE
.
的内置函数
发生的事情是您正在交互式地使用 tclsh
;它检测到这一点并将当前主解释器标记为交互式(将全局 tcl_interactive
变量设置为 1
),未知命令处理程序看到并启用额外的行为,例如扩展命令名称和自动调用外部程序;它实际上是将 date
重写为:
exec {*}[auto_execok date]
Tcl 中的 auto_execok
命令在 bash
或 cmd
中执行路径搜索和 运行 所需的所有额外内容(它有一系列选项可以做)。在我的系统上,auto_execok date
returns /bin/date
,但没有特别的原因为什么它可能会在你的系统上这样做;我们所知道的是它找到了东西.
另一个线程不互动;它不是 直接 跟你说话。这意味着你需要向它发送完整的命令,而不是缩写,而不是简写的东西。默认情况下,它也不会将结果写入控制台;您也需要添加它。试试这个:
set t5 [thread::create]
thread::send -async $t5 "puts \[[list exec {*}[auto_execok "date"]]\]"
这很快就会变得混乱。在另一个线程中创建过程来完成大部分工作然后调用它们要容易得多:
set t5 [thread::create]
thread::send $t5 {
proc runAndPrint {command args} {
puts [exec {*}[auto_execok $command] {*}$args]
}
}
thread::send -async $t5 [list runAndPrint "date"]
请注意,我正在使用 list
来构建要在不是文字时发送的命令。我不需要这样做,但这是一个非常好的习惯,因为这意味着当您开始传递带有空格和其他 meta-characters 的参数时,您的代码将按预期工作™;您不必考虑如何正确引用,因为 list
会为您做到这一点(按设计)。创建要执行的命令很棒,并且保证没有意外替换。如果您需要替换,调用过程(或 lambda 术语或方法)更容易变得可靠;如果需要,可以 uplevel
和 upvar
。
set t6 [thread::create] ; thread::send -async $t6 "set i1 0"
工作正常,没有任何错误。
set t5 [thread::create] ; thread::send -async $t5 "date"
但这是错误的: 执行“date”时命令名称“date”无效
可能是什么原因?
date
“命令”实际上不是命令。这是另一个程序,/bin/date
(或 /usr/bin/date
,具体取决于您的系统设置方式)。或者,在 Windows 上它是 CMD.EXE
.
发生的事情是您正在交互式地使用 tclsh
;它检测到这一点并将当前主解释器标记为交互式(将全局 tcl_interactive
变量设置为 1
),未知命令处理程序看到并启用额外的行为,例如扩展命令名称和自动调用外部程序;它实际上是将 date
重写为:
exec {*}[auto_execok date]
Tcl 中的 auto_execok
命令在 bash
或 cmd
中执行路径搜索和 运行 所需的所有额外内容(它有一系列选项可以做)。在我的系统上,auto_execok date
returns /bin/date
,但没有特别的原因为什么它可能会在你的系统上这样做;我们所知道的是它找到了东西.
另一个线程不互动;它不是 直接 跟你说话。这意味着你需要向它发送完整的命令,而不是缩写,而不是简写的东西。默认情况下,它也不会将结果写入控制台;您也需要添加它。试试这个:
set t5 [thread::create]
thread::send -async $t5 "puts \[[list exec {*}[auto_execok "date"]]\]"
这很快就会变得混乱。在另一个线程中创建过程来完成大部分工作然后调用它们要容易得多:
set t5 [thread::create]
thread::send $t5 {
proc runAndPrint {command args} {
puts [exec {*}[auto_execok $command] {*}$args]
}
}
thread::send -async $t5 [list runAndPrint "date"]
请注意,我正在使用 list
来构建要在不是文字时发送的命令。我不需要这样做,但这是一个非常好的习惯,因为这意味着当您开始传递带有空格和其他 meta-characters 的参数时,您的代码将按预期工作™;您不必考虑如何正确引用,因为 list
会为您做到这一点(按设计)。创建要执行的命令很棒,并且保证没有意外替换。如果您需要替换,调用过程(或 lambda 术语或方法)更容易变得可靠;如果需要,可以 uplevel
和 upvar
。