开发者

Prevent tcl thread from being blocked by main event loop

I am trying to run a thread continuously and not have it become blocked by the tcl main event loop. Here is a simple example of what I'm trying to do:

#!/bin/sh
#\
exec tclsh "$0" "$@"

package require Thread

set ::a_thread [thread::create {thread::wait}]

proc start_a {} {
  thread::send $::a_thread {
    puts "Running a thread"
  }
  after 1000 a_start
}

proc infinite_loop {} {
  while {1} {
    puts "Loop"
    after 500
  }
}

start_a
infinite_loop

vwait forever

In this code开发者_开发技巧, the infinite_loop proc is called and the main event loop runs infinitely. I would like it if the a_thread could still run in the background though. How can I achieve this?


The main event loop is not blocking your thread. Instead you are using the main event loop to shedule scripts to be executed in the thread. Instead, run the scheduler in the thread itself:

Code tested and works as expected:

thread::send $::a_thread {
    proc loop {} {
        puts "running a thread"
        after 1000 loop
    }
    loop
}

while 1 {
    puts "loop"
    after 500
}


The answer is, of course, the one given by slebetman. However, one way to debug this sort of thing (especially in more complex cases) is to prefix the messages printed by each thread by the result of thread::id, and to make sure you print a message at the start of each time round the loop. For example:

package require Thread

set ::a_thread [thread::create {thread::wait}]

proc start_a {} {
  puts "[thread::id]: Dispatch to $::a_thread"
  thread::send $::a_thread {
    puts "[thread::id]: Running a thread"
  }
  after 1000 a_start
}

proc infinite_loop {} {
  while {1} {
    puts "[thread::id]: Loop"
    after 500
  }
}

start_a
infinite_loop
puts "[thread::id]: Start main event loop"
vwait forever

That would have told you that the dispatch was happening once, that the running in the other thread is happening synchronously (thread::send waits for the script to finish executing by default), and that the infinite loop is preventing the startup of the main event loop (and hence the rescheduling of the dispatch). Since you didn't know who was doing what, of course there was confusion!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜