我在tkinter
中有一个应用程序,可以同时从多个websockets接收消息。为了顺序处理这些并避免竞争条件,我将每条消息添加到Queue
,并按顺序处理它们,如下所示:
def queue_msg(self, msg):
self.queue.put(msg)
def process_queue(self):
try:
msg = self.queue.get(0)
except Queue.Empty:
pass
else:
...do stuff...
self.master.after(10, self.process_queue)
只要应用程序正在运行,self.process_queue()
函数就会一直调用自身,以便在后台顺利处理所有邮件。到现在为止还挺好。
我在代码中有几个操作,我需要暂停处理新消息。当这些发生时,我希望应用程序1)停止向队列添加新消息,2)处理队列中已有的所有消息,3)执行操作,以及4)再次开始向队列添加消息。删除临时到达的邮件很好。
我的第一次尝试是定义一个类变量self.pause
,让这些操作将其设置为True
,并在接收新消息时检查这种情况:
def queue_msg(self, msg):
if not self.pause:
self.queue.put(msg)
def process_queue(self):
try:
msg = self.queue.get(0)
except Queue.Empty:
pass
else:
...do stuff...
self.master.after(10, self.process_queue)
def sensitive_operation(self):
self.pause = True
while self.queue.qsize() > 0:
continue
....do stuff....
self.pause = False
但这失败了。 qsize()已经为0,在这种情况下self.pause
出现False
通常会在sensitive_operation()
退出后保持continue
,或者它会卡在after()
的无限循环中}。
显然我误解了self.pause
方法的某些内容,因为pause
的明显更改并未通过各种回调进行一致的传播。有人可以帮助我了解幕后发生的事情,并建议在必要时暂停和清空队列的更好方法吗?
这是一个最小的工作示例。为了模拟来自websocket的消息到达,我使用process_message()函数在处理队列时随机地向队列添加消息。按下continue
按钮大部分时间都可以正常工作,但是如果你将它混搭几次,它最终会挂在import Tkinter as tk
import ttk
import Queue
import numpy as np
class App(tk.Frame):
def __init__(self, parent):
parent.deiconify()
self.parent = parent
self.queue = Queue.Queue()
self.pause = False
self.parent.after(1000, self.process_message)
self.pause_button = tk.Button(parent, text='Pause', command = self.pause_and_empty)
self.pause_button.pack()
def queue_message(self, message):
if not self.pause:
self.queue.put(message)
def process_message(self):
try:
message = self.queue.get(0)
except Queue.Empty:
pass
else:
print message
rand = np.random.rand()
if rand < 0.2:
self.queue_message('test message: {0}'.format(rand))
self.parent.after(10, self.process_message)
def pause_and_empty(self):
self.pause = True
while self.queue.qsize() > 0:
print 'stuck!'
continue
print 'made it!'
self.pause = False
def main():
root = tk.Tk()
root.withdraw()
app = App(root)
root.mainloop()
if __name__=="__main__":
main()
:
pause_and_empty
编辑2:根据第一个答案,对def pause_and_empty(self):
self.pause = True
if self.queue.qsize() > 0:
self.parent.after(10, self.pause_and_empty)
print 'made it!'
函数进行以下调整似乎可以解决问题:
textClock.text = hour + ":" + minute + ":" + second;
答案 0 :(得分:1)
当读取widget.after(milliseconds, callback, *args)
时,它会在 callback
之后将*args
与milliseconds
调用mainloop
的计时器事件排队。方法完成后,python 返回到process_message
行。
示例中的队列永远不会停止,因为对self.pause
的调用永远不会停止,因为它为什么要这样做? False
设置为process_message
,但True
从不检查它是否为manipulateDOM()
。