Reputation: 366
I have a proc named "startMyProc {num}". I want this proc to be called by two different threads and wait for both the threads to complete. I tried the solution given which is working. I want to access the global variables in startMyProc and call a another proc "startMyAnotherProc {num}". How can this be done?
package require Thread
global myVar
set myVar false
set id1 [thread::create -joinable {
source sample.tcl
thread::wait
}]
set id2 [thread::create -joinable {
source sample.tcl
thread::wait
}]
set num 1
thread::send -async $id1 [list startMyProc $num]
set num 2
thread::send -async $id2 [list startMyProc $num]
thread::join $id1
thread::join $id2
My sample.tcl looks like this,
proc startMyProc { num } {
global myVar
puts $myVar
puts "Opening $num"
after 2000
puts "Opening $num"
after 2000
puts "Opening $num"
after 2000
startMyAnotherProc $myVar
return
}
proc startMyAnotherProc { num } {
puts "Opening Another Proc: $num"
after 2000
puts "Opening Another Proc: $num"
after 2000
return
}
Upvotes: 2
Views: 2889
Reputation: 137567
Each thread has its own complete interpreter, isolated from all the other interpreters in your program (except for the thread
package's commands' capabilities). The simplest, most direct way of getting the procedure in all the threads is to put it in a script file and then source
that as part of the startup script of the thread:
set t1 [thread::create -joinable {
source myProcedures.tcl
startMyProc $num
}]
set t2 [thread::create -joinable {
source myProcedures.tcl
startMyProc $num
}]
You'll run into another problem though. Variables are also not shared. That means that you're not going to get $num
over. You should really make the scripts start up and then do thread::wait
at the end. You can then thread::send
them the work (and get the substitutions right when building the script).
set t1 [thread::create -joinable {
source myProcedures.tcl
thread::wait
}]
set t2 [thread::create -joinable {
source myProcedures.tcl
thread::wait
}]
thread::send -async $t1 [list startMyProc $num]
thread::send -async $t2 [list startMyProc $num]
However, if you are really thinking in terms of sending tasks to worker threads, you should look at the thread pool (tpool
) support; it's much easier to scale up.
# Make the thread pool
set pool [tpool::create -initcmd {
source myProcedures.tcl
}]
# Sent the work into the pool as distinct jobs
set job1 [tpool::post $pool [list startMyProc $num]]
set job2 [tpool::post $pool [list startMyProc $num]]
# Wait for all the jobs in the pool to finish
set waitingfor [list $job1 $job2]
while {[llength $waitingfor] > 0} {
tpool::wait $pool $waitingfor waitingfor
}
# Get results now with tpool::get
# Dispose of the pool
tpool::release $pool
Upvotes: 5