1

我编写了一个使用 Tkinter 作为 GUI 的 Python 应用程序。它有第二个线程用于 TCP/IP 通信(实际上是 XMLRPC,允许 labview 连接并进行一些调用)。这两个线程与一对线程安全队列进行通信。运行几天后,它崩溃了。我没有得到完整的追溯。到目前为止,我得到的最好的是 " Tcl_AppendFormatToObj called with shared object" 显然,这来自以下 Tcl 函数:

Tcl_AppendFormatToObj(..)
{
...
    if (Tcl_IsShared(appendObj)) {
    Tcl_Panic("%s called with shared object", "Tcl_AppendFormatToObj");
    }

如果导致问题,有关格式化字符串的一些事情。有什么建议吗?我现在在 winpdb 下的 Windows 7 上运行脚本,等待并希望在“恐慌”再次发生时获得有用的跟踪。

4

2 回答 2

3

事实证明,其中一个队列不是线程安全的。Tk 偶数队列不是线程安全的。因此,使用 tk 的 root.after() 从另一个线程将某些内容放在 tk 的偶数队列中,会导致间歇性问题。相反,创建一个真正的队列,并使非 tk 循环线程向队列中填充一些东西,并使 tk 线程中的代码监视队列的另一端。所以在 tk 循环中,编写一个清空真实队列的函数(并根据它找到的内容做一些事情)。使用 after() 使该函数调用自身。

于 2015-07-05T00:53:56.003 回答
1

TclTcl_Obj值系统的语义——与 Python 不同,它没有值标识——要求值是可观察到的常量。在实践中,这意味着如果有单个引用(例如,来自 Tcl 变量),值可能会被修改,但如果有多个引用(两个变量、一个变量和一个参数等),则值可能不会被修改更改(除了使其类型发生突变,在 Tcl 用语中称为“闪烁”的过程,因为类型并不意味着 Tcl 中值的可观察方面)以防止“幽灵般的远距离”突变。这些规则由值变异函数强制执行,其中Tcl_AppendFormatToObj之一。

为什么有多个对正在变异的值的引用不太清楚。根据您所说的,我猜测您在一个正在改变该值的线程和另一个正在使用该值的线程之间存在竞争(在此期间它临时获取第二个引用)。种族条件很难用所有语言追捕。在低级别,修复通常是使用Tcl_DuplicateObj在变异线程中获取非共享副本,然后可以在进行更改后将其写入共享存储,但我怀疑这会破坏线程代码中的其他地方您可能会在读者方面假设参考不会改变。

整理出来会很棘手。解决这个问题的 Tcl 方法是停止尝试跨线程共享值,而是切换到消息传递,其中“编写器”线程实际上向“读取器”线程发送消息以更新其状态。(如果需要的话,这确实可以扩展到拥有多个阅读器,所以它并不是很糟糕,并且可以在没有全局锁定状态的情况下完成,这甚至更好。Tcl 不需要像 Python 的全局解释器锁这样的东西,因为它分区首先,所有内容都通过线程更加强大。)我不知道如何将其转换为您可以在 Python 中实现的东西……</p>

于 2014-11-20T12:59:21.310 回答