Tcl创建线程并行执行过程:自定义线程无执行动作问题咨询
问题根因
- 子线程未启动事件循环
Tclthread包通过thread::create创建的线程默认不会运行事件循环,而thread::send -async发送的异步任务必须依赖目标线程的事件循环才能被调度执行。你当前使用的主线程默认已启动事件循环(tclsh/wish 默认自带主事件循环),因此给自身发送的异步任务可以正常触发执行,无事件循环的子线程收到任务后不会做任何处理。 - 线程间过程定义相互隔离
Tcl 每个线程对应独立的解释器实例,变量、过程默认完全不共享,你在主线程定义的wa过程仅存在于主线程的解释器中,子线程内部不存在该命令定义。就算子线程启动了事件循环,执行你发送的脚本时也会直接抛出「无效命令名」错误,不会输出预期内容。 - 异步发送模式静默屏蔽错误
thread::send加-async参数后,发送方不会等待目标线程执行结果,也不会捕获目标线程的执行错误,因此你看不到子线程的执行失败提示,直观表现就是子线程没有任何执行动作。
修复示例
# 主线程定义wa过程 proc wa {msg} { puts $msg } # 创建子线程时直接启动事件循环 set thread_loadmaterials [thread::create { vwait run_forever }] # 同步将wa过程的定义传递到子线程 thread::send $thread_loadmaterials [list proc wa [info args wa] [info body wa]] # 发送异步消息,此时两个线程都能正常执行 thread::send -async $thread_loadmaterials [list wa "hola from thread_loadmaterials"] thread::send -async [thread::id] [list wa "hola from thread::id"] # 测试用:等待1秒保证异步任务执行完成后退出 after 1000 exit vwait forever
如果需要快速排查问题,可以先去掉 -async 参数用同步模式发送消息,子线程的执行错误会直接抛到主线程,方便定位问题。
内容的提问来源于stack exchange,提问作者Guillem Ballonga Paretas
相关产品推荐
相关产品推荐

