我想为循环中的每个函数调用创建一个线程。被调用者函数与调用者函数在同一命名空间中,但被调用者函数在执行过程中会从不同的命名空间调用函数。
我是tcl的新手,一直在研究其他SO多线程解决方案,但它们似乎依赖于将被调用者进程本身嵌入线程中,而我正试图避免这种情况。
我也仅限于线程2.7.3,因此线程池不幸不是一个选项。
我也在考虑创建可以并行运行的多个子流程,以更容易的为准,但我想知道解决这个问题的最佳/最简单的方法。提前感谢!
proc process_all_scenarios_multithreaded {results_folder} {
package require Thread 2.7.3
set curr_dir [pwd]
cd $results_folder
foreach scenario $scenario_list {
#package require dai
set sname $scenario'
puts "Scenario: $sname"
set sdir "$curr_dir/$results_folder/$sname"
puts "Results from: $sdir"
set status SUCCESS
set id [thread::create -joinable]
puts "*** Started thread $id"
thread::send -async $id "extract_system_kpis $sname $status $sdir"
lappend threadIds $id
}
# Wait until all other threads are finished
foreach id $threadIds {
thread::join $id
}
}
要模拟线程池,必须考虑
- 制造工人
- 与所述主机通信以获取工作分组
- 执行工作,然后
- 在提取下一个工作项之前,将结果发送回master
您可以根据要分配给池的资源来调整工作人员的数量。通信可以通过您想要的任何机制进行,但使用thread::send
可以在线程之间以及通过管道或套接字发送Tcl列表的进程之间很好地工作。Tcl支持双向管道,所以这样做很容易。
通过管道发送消息只是一件事:
puts $pipe [list ...]
flush $pipe
接收更为复杂,因为你想读行,直到你有一个完整的列表(根据info complete
(。
set accumulator ""
while {1} {
append accumulator [gets $pipe] "n"
if {[info complete $accumulator]} {
process $accumulator
set accumulator ""
} elseif {[eof $pipe]} {
break
}
}
您可能希望eval
接收到的消息,并将结果代码、结果消息和$::errorInfo
作为构建的三元组发回,以便将错误传播到您可以看到它们的位置。