“ package require”命令在TCL线程中不起作用

时间:2019-08-09 06:46:26

标签: tcl

我处理了一个TCL脚本,该脚本需要一些时间才能执行。为了更快地运行它,我想使用Thread包使用多线程。问题是我在名为Hypermesh的工程软件中执行了TCL脚本。它可以很好地支持TCL脚本,因为在软件中可以完成的所有操作都具有关联的TCL命令。 例如,如果用户要使用Hypermesh在坐标(x,y,z)上创建节点,则可以使用命令* createnode $ x $ y $ z获得相同的结果。 回到多线程问题:我可以很好地创建线程,但是在线程内部,我无法使用* createnode命令,因为它无法识别。我猜这是因为某些程序包未装入线程内。我想用“ package require”加载那些丢失的软件包,但是无论我怎么尝试,它都找不到任何软件包。

我发现在线程内,auto_path变量不存在。我尝试创建它,但仍然无法正常工作。 看来我的线程可以执行基本的TCL内置命令,仅此而已。 另一方面,当我使用wish创建线程时,我根本没有这个问题。线程“外部”的所有软件包也都直接“内部”加载。

这是我的代码的样子:

package require Thread
package require Ttrace

set scriptToSend { 
   package require Trf
   return 0
}

set t1 [thread::create]
thread::send -async $t1 $scriptToSend result
puts $result

Trf只是一个随机软件包,当在t1之外调用“ package require”时,可以很好地加载

有什么方法可以将线程设置为具有该线程外部存在的所有命令?例如通过使用包装要求成为可能?

编辑: 我在这个问题上花了更多时间,并尝试使用tpool而不是线程。在tpool中创建的线程似乎“更好”。与线程不同,它们确实具有一个auto_path变量,在使用线程时,我可以使用它成功加载软件包。但是,现在我更多的是Hypermesh问题,因为它不允许我加载使用proc的所有必需包,例如* createnode。 我将通过使我的线程在不使用任何Hypermesh函数的情况下尽其所能来解决该问题。它将仍然大大加快脚本的速度。

1 个答案:

答案 0 :(得分:0)

默认情况下,Tcl在线程中使用全局受限版本的auto_path,因为它的设置方式不完全相同(例如,它不会评估您的~/.tclshrc)。要使用与主线程中相同的程序包,您需要将该变量的副本转移过来。

thread::send $otherThread [list set ::auto_path $::auto_path]

在将其他脚本发送到子线程之前执行此操作,以使事情同步。


在我的系统上,我也会看到这种情况:

bash$ tclsh8.6
% puts $::auto_path
/opt/local/lib/tcl8.6 /opt/local/lib /opt/local/lib/tcllib1.19
% package require Thread
2.8.4
% set otherThread [thread::create]
tid0x7000053ab000
% puts [thread::send $otherThread {set ::auto_path}]
/opt/local/lib/tcl8.6 /opt/local/lib

也有模块路径(可通过tcl::tm::path命令控制),但在子线程中与主线程中的模块路径相同。