1

我正在用 Python 做一个项目,我需要在线程中添加一些东西。事实证明,如果你在线程中做一些使用 Tk 的事情,它会以某种方式崩溃。错误是:

TclError: out of stack space (infinite loop?)`

我在 Google 上搜索过,我认为这可能是因为 Tcl 不是线程安全的。当我运行它时,我得到了 Tcl 错误:

import Tkinter    
Tkinter.Tk().getvar("tcl_platform(threaded)")

据说用 --enable-threads 重新编译 tcl 可以解决这个问题。我的问题是如何在 Windows 中重新编译 tcl。以及如何用编译的替换当前的。我正在使用 Python 2.7 和 Tcl 8.5

谢谢

4

1 回答 1

3

总结:每个 Tk 小部件只能在单个线程中使用;在实现中使用了很多特定于线程的数据,所以这是一个非常硬的要求。你的黑客行为不会解决这个问题。

详细信息: Python 在后台与 Tcl 通信以与 Tk 一起工作,线程化的 Tcl 被设计为强线程绑定(以避免出现 GIL 之类的东西)。可以使用非线程构建,但随后您会遇到代码问题以防止堆栈溢出(幕后非常讨厌的黑客攻击),当它认为它是无线程的时,它会因多个 C 堆栈的存在而感到困惑. 这是您报告的特定错误的来源。Tcl 8.6 中删除了堆栈检查代码(它使用“无堆栈”实现),但这不太可能有帮助,因为除非您处于线程构建中,否则不会尝试处理线程间锁定问题(这需要您回到特定于线程的数据问题)。

非线程模式下的 Tk 对全局共享数据做了很多假设,并且从多个线程中使用非常不安全(所涉及的线程代码的质量可能不是您所希望的,其中大部分可以追溯到底层 OS 库通常也不擅长线程处理)。线程模式下的 Tk 广泛使用 TSD;在线程模式下使用 Tk 的唯一方法是让每个线程都有自己的主窗口和事件循环,并且永远不要在它们之间混淆。

最简单的方法是保留一个专用于管理 GUI 的线程(通常是主应用程序线程)并将所有非 GUI 工作转移到其他线程中。

于 2013-07-09T08:53:49.517 回答