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

发布于 2024-10-03 15:57:07 字数 500 浏览 0 评论 0原文

我试图连续运行一个线程,而不让它被 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 过程,并且主事件循环无限运行。如果 a_thread 仍然可以在后台运行,我希望它。我怎样才能实现这个目标?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

优雅的叶子 2024-10-10 15:57:07

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

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

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

while 1 {
    puts "loop"
    after 500
}

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
}
信仰 2024-10-10 15:57:07

答案当然是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 默认情况下等待脚本完成执行),并且无限循环阻止主事件循环的启动(从而阻止重新调度调度)。既然你不知道谁在做什么,当然会很混乱!

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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文