TCL thread::send upvar 变量未设置
TCL thread::send upvar variable not being set
我有这样的代码:
package require Thread
proc p1 {} {
set tid [thread::create {
proc executeCommand {command} {
return $command
}
thread::wait
}]
set result ""
::thread::send -async $tid [list executeCommand {"Hello thread world"}] result
#***Do some additional stuff***
vwait result
::thread::release $tid
puts $result
return $result
}
p1
获取包含此代码的 .tcl 文件后,我的期望是子线程在调用 vwait 并打印出 'result' 变量后 return "Hello thread world" , 但这些都没有发生。 'result' 变量似乎仍为空白。
奇怪的是,当我从过程 (proc) 块中取出代码并获取 .tcl 文件时,它工作得很好,但是根据我的系统设置方式,我需要使用过程。
不确定我做错了什么。
“问题”是接收变量(就像 vwait
)是相对于全局命名空间定位的,而不是当前范围内的变量;标志 TCL_GLOBAL_ONLY
用于 the call to Tcl_SetVar2Ex
in the callback(Tcl 的底层变量实现非常复杂,所以如果可能的话,人们真的想坚持使用 API):
/*
* Set the result variable
*/
if (Tcl_SetVar2Ex(interp, var, NULL, valObj,
TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG) == NULL) {
rc = TCL_ERROR;
goto cleanup;
}
这通常是有道理的,因为您 可以 从启动后台线程和接收结果之间的过程返回,而 Tcl 确实 尽量避免进行早期绑定。
那么结果去哪儿了?它在 global result
变量中(::
只是意味着“我真的想使用这个命名的全局变量”):
% puts $::result
"Hello thread world"
最简单的解决方法是使用一个变量来接收特定呼叫所特有的。这听起来比实际情况更复杂,因为我们已经在线程 ID 中获得了一个唯一标记:
proc p1 {} {
set tid [thread::create {
proc executeCommand {command} {
return $command
}
thread::wait
}]
### Make the name of the global variable (an array element) ###
set var ::p1results($tid)
### This is a simple transformation of what you were already doing ###
set $var ""
::thread::send -async $tid [list executeCommand {"Hello thread world"}] $var
#***Do some additional stuff***
vwait $var
### Transfer the global variable into a local and remove the global ###
set result [set $var]
unset $var
### Back to your code now ###
::thread::release $tid
puts $result
return $result
}
当我尝试时,这似乎按预期工作。
我有这样的代码:
package require Thread
proc p1 {} {
set tid [thread::create {
proc executeCommand {command} {
return $command
}
thread::wait
}]
set result ""
::thread::send -async $tid [list executeCommand {"Hello thread world"}] result
#***Do some additional stuff***
vwait result
::thread::release $tid
puts $result
return $result
}
p1
获取包含此代码的 .tcl 文件后,我的期望是子线程在调用 vwait 并打印出 'result' 变量后 return "Hello thread world" , 但这些都没有发生。 'result' 变量似乎仍为空白。
奇怪的是,当我从过程 (proc) 块中取出代码并获取 .tcl 文件时,它工作得很好,但是根据我的系统设置方式,我需要使用过程。
不确定我做错了什么。
“问题”是接收变量(就像 vwait
)是相对于全局命名空间定位的,而不是当前范围内的变量;标志 TCL_GLOBAL_ONLY
用于 the call to Tcl_SetVar2Ex
in the callback(Tcl 的底层变量实现非常复杂,所以如果可能的话,人们真的想坚持使用 API):
/*
* Set the result variable
*/
if (Tcl_SetVar2Ex(interp, var, NULL, valObj,
TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG) == NULL) {
rc = TCL_ERROR;
goto cleanup;
}
这通常是有道理的,因为您 可以 从启动后台线程和接收结果之间的过程返回,而 Tcl 确实 尽量避免进行早期绑定。
那么结果去哪儿了?它在 global result
变量中(::
只是意味着“我真的想使用这个命名的全局变量”):
% puts $::result
"Hello thread world"
最简单的解决方法是使用一个变量来接收特定呼叫所特有的。这听起来比实际情况更复杂,因为我们已经在线程 ID 中获得了一个唯一标记:
proc p1 {} {
set tid [thread::create {
proc executeCommand {command} {
return $command
}
thread::wait
}]
### Make the name of the global variable (an array element) ###
set var ::p1results($tid)
### This is a simple transformation of what you were already doing ###
set $var ""
::thread::send -async $tid [list executeCommand {"Hello thread world"}] $var
#***Do some additional stuff***
vwait $var
### Transfer the global variable into a local and remove the global ###
set result [set $var]
unset $var
### Back to your code now ###
::thread::release $tid
puts $result
return $result
}
当我尝试时,这似乎按预期工作。