作者:书友31617792 | 来源:互联网 | 2023-05-23 12:27
我曾经在C中工作,其中线程很容易用我选择的特定函数创建.
现在在tcl我不能使用线程来启动我想要的特定功能,我试过这个:
package require Thread
proc printme {aa} {
puts "$aa"
}
set abc "dasdasdas"
set pool [tpool::create -maxworkers 4 ]
# The list of *scripts* to evaluate
set tasks {
{puts "ThisisOK"}
{puts $abc}
{printme "1234"}
}
# Post the work items (scripts to run)
foreach task $tasks {
lappend jobs [tpool::post $pool $task]
}
# Wait for all the jobs to finish
for {set running $jobs} {[llength $running]} {} {
tpool::wait $pool $running running
}
# Get the results; you might want a different way to print the results...
foreach task $tasks job $jobs {
set jobResult [tpool::get $pool $job]
puts "TASK: $task"
puts "RESULT: $jobResult"
}
我总是得到:执行错误206:无效的命令名称"printme"无效命令名称"printme"执行"printme"1234""从"tpool :: get $ pool $ job"中调用
为什么?
1> schlenk..:
问题是,Tcl线程模型与C中使用的模型非常不同.Tcl的模型基本上是基于消息传递的"默认情况下无共享"模型.
因此,池中的每个线程都是一个独立的解释器,并且对proc
printme一无所知.您需要使用所需的过程来初始化这些解释器.
请参阅该::tpool::create
命令的文档,它可以选择提供-initcmd
您可以定义的位置或package require
所需的内容.
所以试试这个来初始化你的线程:
set pool [tpool::create -maxworkers -initcmd {
proc printme {aa} {
puts "$aa"
}}]
https://www.tcl.tk/man/tcl/ThreadCmd/tpool.htm#M10
更详细地回答你的评论:
不,没有办法让Tcl线程像C线程一样工作,并且可以自由地共享对象和proc.这是一个基本的设计决策,允许Tcl拥有一个没有大量全局锁定的解释器(与CPython相比),因为大多数东西都是线程本地的并且使用线程本地存储.
但是有一些方法可以更容易地初始化和使用多个线程解释器.一个-initcmd
参数::tpool::create
允许您为池中的每个解释器运行初始化代码,而无需手动执行.如果您的所有代码都存在于一个包中,您只需添加一个package require
并且您的解释器已正确初始化.
如果您确实希望在多个线程之间共享状态,则可以使用::tsv
子命令.它允许您以明确的方式在线程之间共享数组和其他内容.但在引擎盖下它涉及您可能从C中知道的典型锁和互斥量来调解访问.
包中还有另一组命令thread
,可以让您更容易进行初始化.这是ttrace
命令,它允许您简单地trace
在一个解释器中执行的操作,并在另一个解释器中自动重复它.它非常智能,只能将您真正使用的触发器共享/复制到目标,而不是预先加载所有内容.