简体   繁体   中英

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

I am trying to create a basic console window using tkinter. My current code has two classes, one for the gui and one for adding text to the console. The text adding class is running in a different thread than the gui (which is running in the main thread). 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. 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).

Short answer: You can only get an entry from a Queue once. If the worker reads it immediately, the main thread can't (and vice versa).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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