防止tcl线程被主事件循环阻塞

时间:2010-11-19 03:43:38

标签: multithreading tcl

我正在尝试连续运行一个线程,而不是让它被tcl主事件循环阻塞。 这是我正在尝试做的一个简单示例:

#!/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

在此代码中,调用infinite_loop proc并且主事件循环无限运行。如果a_thread仍然可以在后台运行,我希望如此。我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:6)

主事件循环没有阻塞你的线程。相反,您使用主事件循环来指示要在线程中执行的脚本。相反,在线程本身中运行调度程序:

代码经过测试并按预期工作:

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

while 1 {
    puts "loop"
    after 500
}

答案 1 :(得分:5)

答案当然是由slebetman给出的答案。但是,调试此类事情的一种方法(特别是在更复杂的情况下)是为每个线程打印的消息添加thread::id的结果前缀,并确保打印一个每次围绕循环的开始的消息。例如:

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

那会告诉你调度发生一次,其他线程中的运行是同步发生的(thread::send等待脚本默认完成执行),并且无限循环阻止了启动主事件循环(因此重新安排调度)。既然你不知道谁在做什么,当然有混乱!