【发布时间】:2013-12-04 22:41:29
【问题描述】:
我想明白为什么我会收到以下错误TclStackFree: incorrect freePtr. Call out of sequence?,但我不知道如何解决这个问题。
我的脚本摘要
我的Python、TKinter 脚本由三个活动线程组成。主线程和两个子线程。其中一个子线程负责侦听 UDP 消息,另一个负责绘制接收到的数据(使用 Matplotlib)。据我所知,问题是我试图从两者访问 gui同时子线程。例如,我可能正在接收 UDP 消息并尝试在 gui 上显示它们,同时尝试绘制以前接收到的数据的图形。这并不少见,因为我接收 UDP 数据包的速率(高达每秒 10,000 个)。
代码
两个子线程使用 -
thread.start_new_thread(self.function, ())
UDP 监听线程
def Listen(self):
if self.udpClient.IsConnected():
while True:
#Listen for messages
data = self.udpClient.listen(1024)
#Add the data to the gui
self.AddNewData(data)
if self.disconnectFlag:
break
def AddNewData(self, data):
self.listbox.insert(END, data)
receivedData.append(data)
图形线程
def UpdateGraph(self):
while True:
if readyToGraph:
self.plot.clear()
self.plot.hexbin(data[0], data[1], bins = "log", extent = self.extent)
self.canvas.draw()
EDIT:
if __name__ == "__main__":
root = TK()
gui = MainWindow(root, "Receiver")
root.mainloop()
就像我说的那样,我认为问题在于有时侦听器线程尝试将数据添加到列表框,同时图形线程尝试更新图形。
我试过了...
在尝试修改 GUI 之前使用 root.after_idle(...) 但这只会锁定主线程。示例:self.listbox.insert(END, data) -> root.after_idle(self.listbox.insert, END, data)(我在 self.plot.clear()、self.plot.hexbin(...) 和 self.canvas.draq() 之前也调用了 root.after_idle)
我还按照建议查看了threading.condition 和queue.queue here,但我找不到太多关于这两个的信息。 (所以我还没有真正尝试过任何一种解决方案)
问题
如何从子线程访问 gui 而不锁定它或导致上述错误?
【问题讨论】:
-
90% 确定你必须在主线程上进行绘图。
-
@tcaswell 打电话给
root.after_idle? (root我的意思是TK,对不起,我是想在问题中说明这一点) -
另外,如果您正在嵌入,请不要导入
pyplot(我不知道您是否是)。也不要使用plot作为名称,它技术上不会与plot()冲突,但它会使您的代码非常难以阅读。 -
我对 tk 和线程没有太多经验,但是使用 QT 你不能从工作线程调用任何绘图函数。我假设 TK 有某种回调或计时器来告诉主线程在准备好时查看来自读取器线程的数据
-
如果我不担心将数据添加到列表框中,只需绘制数据图表,那么一切正常。所以这让我觉得我可以在不进入主线程的情况下绘制图表..
标签: python multithreading matplotlib tkinter