我正在尝试使用tkinter创建一个基本的控制台窗口。我当前的代码有两个类,一个用于gui,另一个用于向控制台添加文本。文本添加类在与gui(在主线程中运行)不同的线程中运行。我有一个队列设置来在两个线程之间进行通信。一切都有效,除了队列。当我向队列添加文本时,可以从工作线程读取它,但不能从主线程读取。这是我的代码:
import threading, sys, os, time, Queue
from Tkinter import *
class consolegui:
"""Main GUI for the program"""
def __init__(self, root):
self.root=root
self.cout=Text(self.root, width=80)
self.root.after(100, self.process_queue)
self.cout.config(state=DISABLED)
self.cout.pack(side=TOP)
self.bottomf=Frame(self.root, height=1, width=80)
self.bottomf.pack(side=BOTTOM)
self.cin=Entry(self.bottomf, width=100)
self.cin.pack(side=LEFT)
self.enter=Button(self.bottomf, text="send", command=self.on_click)
self.cin.bind('<Return>', self.on_click)
self.enter.pack(side=BOTTOM)
self.queue = Queue.Queue()
worker(self.queue).start()
def on_click(self, *args):
self.cout.config(state=NORMAL)
self.cout.insert(END, self.cin.get()+'\n')
self.cout.config(state=DISABLED)
self.cin.delete(0, END)
def add_text(self, text):
self.cout.insert(END, text+'\n')
def process_queue(self):
print "reading queue"
try:
msg = self.queue.get(0)
print "found items in queue!"
self.add_text(msg)
with self.queue.mutex:
self.queue.queue.clear()
except Queue.Empty:
print "found nothing"
self.root.after(100, self.process_queue)
class worker(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
time.sleep(5)
print "adding to queue"
self.queue.put("Task finished")
print self.queue.get(0)
if __name__ == "__main__":
root = Tk()
console=consolegui(root)
root.mainloop()
感谢您的帮助!
答案 0 :(得分:0)
你确定主线程无法读取吗?您正在使用非阻塞get
,并在检查之间休眠。工作者只向队列添加一个项目,并立即将其读回(这会清空队列)。您创建的竞争条件要求Python GIL在put
和get
之间以正确的100秒标记交换到主线程完全在检查之间(和写的一样,看起来你在五秒钟之后就加入了所以它可能还有95秒的时间,并且这种比赛永远不会发生。)
简短回答:您只能get
Queue
一次{{1}}条目。如果工作人员立即读取它,则主线程不能(反之亦然)。