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

elm*_*lmt 1 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
Run Code Online (Sandbox Code Playgroud)

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

sle*_*man 6

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

代码测试并按预期工作:

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

while 1 {
    puts "loop"
    after 500
}
Run Code Online (Sandbox Code Playgroud)


Don*_*ows 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
Run Code Online (Sandbox Code Playgroud)

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