我编写了一个TCL脚本,它需要一些时间来执行。为了更快地运行它,我想使用多线程使用线程包。问题是我在一个名为Hypermesh的工程软件中执行我的TCL脚本。它很好地支持TCL脚本,因为在软件中可以完成的所有操作都有一个相关的TCL命令。例如,如果用户要使用Hypermesh在坐标(x,y,z)创建一个节点,那么可以使用命令*createnode $x $y $z获得相同的结果。回到多线程问题:我可以很好地创建线程,但是在线程内部,我不能使用命令*createnode,因为它是不被识别的。我猜这是因为有些包没有加载到线程中。我想加载那些丢失的包与“包要求”,但无论我如何尝试,它找不到任何软件包。
我发现线程中不存在auto_path变量。我试着创建它,但它仍然不能工作。看起来我的线程可以执行基本的TCL in命令,而且什么也不能执行。另一方面,当我使用have创建线程时,我根本没有这个问题。所有“在线程外”的包也直接加载到“内部”。
下面是我的代码的样子:
package require Thread
package require Ttrace
set scriptToSend {
package require Trf
return 0
}
set t1 [thread::create]
thread::send -async $t1 $scriptToSend result
puts $resultTrf只是一个随机包,在t1外部调用“”时可以很好地加载它。
是否有任何方法可以设置线程,使所有存在于线程之外的命令?例如,通过使用包要求的可能?
编辑:我花了更多的时间在这个问题上,并试图使用tpool而不是线程。在tpool中创建的线程看起来“更好”。与线程不同,它们确实有一个auto_path变量,我可以使用它在使用线程时成功地加载包。然而,现在我有了更多Hypermesh问题,因为它不允许我加载所有必要的包来使用procs,比如*createnode。我将尽量让线程在不使用任何Hypermesh函数的情况下完成尽可能多的任务,从而解决这个问题。它仍然会大大加快剧本的速度。
发布于 2019-08-10 05:31:21
默认情况下,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命令可以控制),但在子线程中和主线程中是一样的。
https://stackoverflow.com/questions/57424723
复制相似问题