我认为理解为什么我收到以下错误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)
(我在root.after_idle
,self.plot.clear()
和self.plot.hexbin(...)
之前也称self.canvas.draq()
}
我还按照 here 的建议调查了threading.condition
和queue.queue
,但我找不到有关这两者的更多信息。 (所以我还没有尝试过任何一种解决方案)
如何从子线程访问gui而不将其锁定或导致上述错误?
答案 0 :(得分:0)
以下是tkinter-discuss邮件列表中讨论内容的链接: https://mail.python.org/pipermail/tkinter-discuss/2013-November/thread.html
这是本质:
您好,
afaik after()/ after_idle()调用不是线程安全的!
在我的研究导致代码安德烈亚斯提供我找到了 event_generate()方法是调用tk的唯一线程安全方式 线程,而不让它进行轮询。 (如Guido和 在其他页面上看到其他人似乎都在调查...为什么?)
brgds,
- Jan