2016-08-08 111 views
0

Ich bin auf der Suche nach "beste" Möglichkeit, Treeview mit Threads zu füllen. Ich habe mehrere E-Mail-Konten, die ich auf neue E-Mails überprüfe.tkinter bevölkern Baumansicht mit Threading Pool

Mein Plan ist Queue zu verwenden Konten zu speichern, die mit check_mail Methode geprüft werden. Diese Methode wird eine Liste von neuen Mails zurückgeben.

Kann ich einen anderen Queue verwenden, den ich mit neuen Mails befüllen werde und irgendwie Schleife, während Threads leben?

Gibt es irgendein fadensicheres, gutes Muster, um das zu lösen?

Antwort

0

Ihre Frage ist sehr breit, also wird diese Antwort auch sein.

Im Allgemeinen spielt tkinter nicht gut mit Multithreading. Sie können es tun, müssen aber sicherstellen, dass nur der Haupt-Thread mit der GUI interagiert. Ein üblicher Weg, dies zu tun, besteht darin, die universal widget methodafter() zu verwenden, um die Behandlung von Daten, die zu Hintergrundthreads ausgehen oder von diesen abgerufen werden, typischerweise in regelmäßigen Abständen über Queue s zu planen.

+0

Gibt es eine gute Beispiele? Ich habe das gefunden (http://effbot.org/zone/tkinter-threads.htm), aber es spiegelt nicht, was ich brauche. Es gibt genau das gleiche Beispiel [hier] (http://stackoverflow.com/questions/16860961/python-tkinter-multithreading-functions), aber ich finde es nicht nützlich. – sstevan

+0

Etwas in dieser Richtung ist in der "errorwindow.py" in [dieser Antwort] (http://stackoverflow.com/a/18091356/355230) von mir auf eine andere Frage dargestellt. Es ist ein wenig schwierig, da das Modul sowohl direkt importiert als auch indirekt als separater Prozess von der Hauptanwendung erzeugt wird. Es hat auch nur eine Warteschlange, es gibt also keinen bidirektionalen Datenfluss. Das Wichtigste wäre, die Verwendung von 'after()' zur Handhabung der 'Queue' zu ​​beachten. – martineau

+0

Danke für die Hilfe! Ich werde diese Antwort als korrekt und post (vielleicht nicht so toll) Lösung markieren. – sstevan

0

Ich bin mir nicht sicher, ob dies die beste Idee ist, aber es funktioniert

class Main(tk.Frame): 

    def __init__(self, master):  
     tk.Frame.__init__(self, master) 
     self.master = master 
     self.some_service = SomeService() 
     self.some_service.run() 
     self.init_gui() 
     self.after(60000, self.check_for_updates) # Use it to run service 
     self.after(2000, self.update_gui) # Update GUI every 2 seconds. 

    def check_for_updates(self): 
     data = ['a', 'b', 'c', 'd'] 
     self.some_service.populate_job_queue(data) 
     self.after(60000, self.check_for_updates) 

    def update_gui(self): 
     if not self.some_service.update_queue.empty(): 
      update = self.some_service.update_queue.get() 
      ## Do something with update ## 
      self.text.insert(tk.END, update) 
     self.after(2000, self.update_gui) 


class SomeService(object): 

    def __init__(self): 
     self.update_queue = Queue() 
     self.job_queue = Queue() 

    def populate_job_queue(self, jobs): 
     for job in jobs: 
      self.job_queue.put(job) 

    def run(self): 
     for x in range(8): 
      worker = Thread(target=self.do_something, daemon=True) 
      worker.start() 

    def do_something(self): 
     ## Do something with data 
     while True: 
      if not self.job_queue.empty(): 
       job = self.job_queue.get() 
       # Do something 
       self.update_queue.put(some_data) 
+0

Ein Problem damit kann die Tatsache sein, dass es einen Ausbruch von Multi-Threading nur einmal alle 60 Sekunden gibt, während der die GUI effektiv hängt, bis sie alle im Leerlauf sind (wegen der 'self.pool.join()' at das Ende von 'run()' Blöcken). Ich denke, was Sie tun wollen, ist, dass die Threads potentiell die ganze Zeit in einer Warteschlange stehen und die Haupt-GUI periodisch (über 'after()') Dinge davon abrufen und alle betroffenen Widgets aktualisieren, falls nötig. – martineau

+0

@martineau Danke! Ich habe es an meine Bedürfnisse angepasst. Habe das obige Beispiel nicht getestet, aber ich hoffe es funktioniert. – sstevan

+0

Sieht so aus, als ob das Update die Dinge angesprochen hat, die ich erwähnt habe. Die Einrückung der 'update_gui()' Methode ist allerdings ein wenig aus. '' '' ' – martineau