首页 > 解决方案 > tcl 多线程:在循环中多次调用函数的最佳方法

问题描述

我想为循环中的每个函数调用创建一个线程。被调用函数与调用函数在同一个命名空间中,但被调用函数在执行期间从不同的命名空间调用函数。

我是 tcl 的新手,并且一直在寻找其他 SO 多线程解决方案,但它们似乎依赖于将被调用程序本身嵌入到我试图避免的线程中。

我也仅限于 Thread 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
    }
}

标签: multithreadingtcl

解决方案


要模拟线程池,您必须考虑以下方面

  1. 使工人,即
  2. 与master通信以获取工作包,
  3. 执行工作,然后
  4. 在拾取下一个工作项之前将结果发送回主控。

您可以使用希望分配给池的资源来扩展工作人员的数量。可以通过任何你想要的机制进行通信,但是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构建的三元组发回,以便将错误传播到您可以看到它们的地方。


推荐阅读