首页 > 解决方案 > TCL:thread::send 命令正在主线程中运行,而不是发送命令中提到的线程 id

问题描述

下面是为我现有的单(主线程)线程脚本实现多线程而编写的示例脚本。

# Wrapper proc for executing passed procedure list
proc eval_procs {dut_no procList} {
telnet_dut $dut_no ;# proc to change telnet id to $dut_no
puts "thread id: [thread::id]"
foreach procedure [join [list $procList]] {
    eval [join $procedure]
  }
}

for {set i 0} {$i <= 1} {incr i} {            
lappend jointhreadIds [thread::create]            
}

set dutList [list 1 2]
set dutConfigList [list [list "get_port_statistics_mt 1"] [list "c_get_port_statistics_mt 2"]] ;#proc for getting port statistics from switch 1 and 2

for {set i 0} {$i <= 1} {incr i} {            
thread::send -async [lindex $jointhreadIds $i] [eval_procs [lindex $dutList $i] [lindex $dutConfigList $i]]             
}

为每个开关调用相同的 proc (eval_procs) 创建了两个线程。但是,当使用 thread::send -async 调用 proc 时,此 proc 将依次为 switch1 调用,然后为 switch2 调用。在 eval_procs 中打印 thread::id 后,我发现这些 procs 在主线程中运行,这就是顺序运行的原因。

有人在这里帮助我,我在这里犯了什么错误或任何其他要遵循的程序?

下面的帖子提到在创建线程时在脚本中定义 procs,但对我来说,我有很多已经开发的库 (procs) 可以在主线程中正常工作。所以,我不能移动 thread::create 下的所有库。

https://stackoverflow.com/a/32154589/13100284

标签: multithreadingtclsend

解决方案


通常,您在主解释器中创建的任何自定义过程(或 C 命令)都不会在其他线程的解释器中创建。您可以使用 Thread 包的ttrace系统进行复制,但您需要显式加载所需的任何额外 C 命令。(我更喜欢将所有需要的东西放在包中,然后package require根据需要放在每个工作线程中,但这更复杂。)

package require Ttrace

# Procedures created in here get replicated to current and future threads
ttrace::eval {
    # Wrapper proc for executing passed procedure list
    proc eval_procs {dut_no procList} {
        telnet_dut $dut_no ;# proc to change telnet id to $dut_no
        puts "thread id: [thread::id]"
        foreach procedure [join [list $procList]] {
            eval [join $procedure]
        }
    }
    # You probably need to create the other commands here; I don't know your code, but you can source them just fine
}

# Now, the rest of your code as normal.
for {set i 0} {$i <= 1} {incr i} {
    lappend jointhreadIds [thread::create]
}

set dutList [list 1 2]
set dutConfigList [list [list "get_port_statistics_mt 1"] [list "c_get_port_statistics_mt 2"]]; #proc for getting port statistics from switch 1 and 2

for {set i 0} {$i <= 1} {incr i} {
    thread::send -async [lindex $jointhreadIds $i] [eval_procs [lindex $dutList $i] [lindex $dutConfigList $i]]
}

请注意,您可能还有其他错误。最后一个命令冒犯了我,因为它应该使用多列表foreach并构建命令以使用list. 在这里,我的意思是它应该是这样的:

foreach  t_id $joinThreadIds  dut_no $dutList  dut_config $dutConfigList  {
    # I've split the next line in two for even more clarity
    thread::send -async $t_id [list \
            eval_procs $dut_no $dut_config]
}

推荐阅读