简体   繁体   English

从工作线程添加到主线程后,该队列为空

[英]Queue in main thread is empty after adding to it from worker thread

I am trying to create a basic console window using tkinter. 我正在尝试使用tkinter创建一个基本的控制台窗口。 My current code has two classes, one for the gui and one for adding text to the console. 我当前的代码有两类,一类用于gui,一类用于向控制台添加文本。 The text adding class is running in a different thread than the gui (which is running in the main thread). 文本添加类在与gui不同的线程中运行(在主线程中运行)。 I have a queue set up to communicate between the two threads. 我设置了一个队列来在两个线程之间进行通信。 Everything works except for the queue. 除队列外,其他所有内容均正常。 When I add text to the queue, it can be read from the worker thread but not the main thread. 当我将文本添加到队列时,可以从工作线程中读取文本,而不能从主线程中读取文本。 Here is my code: 这是我的代码:

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()

Thanks for any help! 谢谢你的帮助!

Are you sure it's not readable from the main thread? 您确定它不能从主线程读取吗? You're using a non-blocking get , and sleeping between checks. 您正在使用非阻塞的get ,并且在两次检查之间处于休眠状态。 The worker only adds a single item to the queue, and reads it back immediately (which empties the queue). 工作人员仅将单个项目添加到队列,然后立即读回(清空队列)。 The race condition you've created would require the Python GIL to swap to the main thread exactly between the put and the get at the exact 100 second mark between checks (and as written, it looks like you're adding after five seconds so it's likely got ~95 seconds to go, and that race will never happen). 您创建的竞态条件将要求Python GIL在检查之间的准确100秒标记之间准确putget之间切换到主线程(并且按照书面说明,您似乎在五秒钟后添加,因此大概还有95秒的路程,而这场比赛将永远不会发生)。

Short answer: You can only get an entry from a Queue once. 简短的答案:您只能从Queue get一个条目。 If the worker reads it immediately, the main thread can't (and vice versa). 如果工作人员立即读取它,则主线程无法读取(反之亦然)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM