2013-02-04 7 views
12

değil, benRuntimeError: Ana iş parçacığı benim Python programında</p> <pre><code>self.client = ThreadedClient() </code></pre> <p>diyoruz ana döngü

"RuntimeError: main thread is not in main loop"

Zaten bazı googling yaptık hatayı olsun, ancak bir yapıyorum Bir şekilde hata ... Birisi bana yardım edebilir mi?

Tam hatası:

Exception in thread Thread-1: 
    Traceback (most recent call last): 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 530, in __bootstrap_inner 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 483, in run 
    File "/Users/Wim/Bird Swarm/bird_swarm.py", line 156, in workerGuiThread 
    self.root.after(200, self.workerGuiThread) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 501, in after 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1098, in _register 
    RuntimeError: main thread is not in main loop 

Sınıflar: Sen ana iş parçacığı dışında dizisindeki ana GUI döngü koşuyoruz

class ThreadedClient(object): 

    def __init__(self): 
     self.queue = Queue.Queue() 
     self.gui = GuiPart(self.queue, self.endApplication) 
     self.root = self.gui.getRoot() 
     self.running = True 
     self.GuiThread = threading.Thread(target=self.workerGuiThread) 
     self.GuiThread.start() 

    def workerGuiThread(self): 
     while self.running: 
      self.root.after(200, self.workerGuiThread) 
      self.gui.processIncoming()  

    def endApplication(self): 
     self.running = False 

    def tc_TekenVogel(self,vogel): 
     self.queue.put(vogel) 

class GuiPart(object): 
    def __init__(self, queue, endCommand): 
     self.queue = queue 
     self.root = Tkinter.Tk() 
     Tkinter.Canvas(self.root,width=g_groottescherm,height=g_groottescherm).pack() 
     Tkinter.Button(self.root, text="Move 1 tick", command=self.doSomething).pack() 
     self.vogelcords = {} #register of bird and their corresponding coordinates 

    def getRoot(self): 
     return self.root 

    def doSomething(): 
     pass #button action 

    def processIncoming(self): 
     while self.queue.qsize(): 
      try: 
       msg = self.queue.get(0) 
       try: 
        vogel = msg 
        l = vogel.geeflocatie() 
        if self.vogelcords.has_key(vogel): 
         cirkel = self.vogelcords[vogel] 
         self.gcanvas.coords(cirkel,l.geefx()-g_groottevogel,l.geefy()-g_groottevogel,l.geefx()+g_groottevogel,l.geefy()+g_groottevogel)    
        else: 
         cirkel = self.gcanvas.create_oval(l.geefx()-g_groottevogel,l.geefy()-g_groottevogel,l.geefx()+g_groottevogel,l.geefy()+g_groottevogel,fill='red',outline='black',width=1) 
         self.vogelcords[vogel] = cirkel 
        self.gcanvas.update() 
       except: 
        print('Failed, was van het type %' % type(msg)) 
      except Queue.Empty: 
       pass 
+0

Geri izlemenizden, "workerGuiThread" işlevini, yürütme işleminin ana yerine başka bir yerde oluşturduğunuz bir iş parçacığından çalıştırıyormuşsunuz gibi görünüyor. TK uzmanı değilim, ama hataya izin verilmediğini gösteriyor gibi görünüyor (ana dizgeyi kullanmak için TK işlevlerini çağırmak zorundasınız, 'sonra' gibi). – Blckknght

+0

[Bu soru] bölümüne bakın (http://stackoverflow.com/questions/3567238/i-need-a-little-help-with-python-tkinter-and-threading), [bu yanıt] (http: // stackoverflow TkInter'ın çok iş parçacıklı bir programda kullanılmasıyla ilgili bazı ayrıntılar için .com/a/10556698/908494) vb. Ama kısa versiyon: Sadece ana thread, period'ta kullanın. – abarnert

+0

Hey Blckknght. Bu yüzden mtTkinter kullanıyorum. – user2040823

cevap

17

. Bunu yapamazsın.

Dokümanlar, Tkinter'in pek de çok dişli olmadığından emin olmayan birkaç yerden bahseder, ama bildiğim kadarıyla, asla çıkıp sadece ana iş parçasından Tk ile konuşabileceğinizi söyleyin. Bunun nedeni, gerçeğin biraz karmaşık olmasıdır. Kendiliğinden , iş parçacığı için güvenli, ancak çok iş parçacıklı bir şekilde kullanmak zordur. Bu konuda resmi belgelere yakın this page gibi görünüyor:

Q. Is there an alternative to Tkinter that is thread safe?

Tkinter?

Just run all UI code in the main thread, and let the writers write to a Queue object…

(Verilen örnek kod büyük değil, ama onlar söylüyoruz anlamaya ve düzgün şeyler yapmak için yeterli olacaktır.)

Aslında, ,, Tkinter, mtTkinter'a uygun bir diş güvenli alternatifidir. Ve dokümanlar aslında oldukça iyi durumu açıklar:

Although Tkinter is technically thread-safe (assuming Tk is built with --enable-threads), practically speaking there are still problems when used in multithreaded Python applications. The problems stem from the fact that the _tkinter module attempts to gain control of the main thread via a polling technique when processing calls from other threads.

bu görüyorsanız tam olarak ne olduğuna inanıyoruz: senin Tkinter kodunu Konu-1 ana döngü bulmak için ana iş parçacığı gözetleme çalışıyor ve orada değil.

  • Tkinter dokümanlar tavsiye gerekeni yap ve ana iş parçacığı gelen Tkinter kullanın:

    Yani, burada bazı seçeneklerdir. Mevcut ana iş parçacığınızı bir çalışan iş parçacığına taşıyarak mümkündür.
  • Ana iş parçacığını (örneğin, twisted) ele almak isteyen başka bir kitaplık kullanıyorsanız, Tkinter ile tümleştirmenin bir yolu olabilir, bu durumda bunu kullanmalısınız. Bu sorunu çözmek için mkTkinter kullanın.

Ayrıca, bu sorunun tam bir kopyasını bulamadığım halde, SO ile ilgili birçok soru vardır. Daha fazla bilgi için bkz. this question, this answer ve daha fazlası.

+0

Hey abarnert. Cevabınız için teşekkürler. MtTkinter ile opsiyon için kullandım. Kodum çalışıyor (hatasız demek istiyorum). Ama tuvali göremiyorum ... Günlüğümde programın çalıştığını görüyorum ... sadece görselleştirme olmadan. @ Https://github.com/wimhendrickx/Flocking/blob/master/bird_swarm.py kodunu göremezsiniz. Şimdiden teşekkürler. – user2040823

+0

@ user2040823: Neden kodu göremiyorum, beyaz bir arka planda beyaz yazıyla mı? :) Neyse, indirip bir göz atacağım. – abarnert

+0

@ user2040823: Tamam, burada çok sayıda temel problem var. Öncelikle, 'root.mainloop()' yi hiçbir yerde aramıyorsunuz. İkincisi, 'self' almayan 'doSomething' gibi yöntemlere sahipsiniz (ve staticmethod'un değil). Üçüncü olarak, 'Tkinter' olay işleyicileriniz bir 'event' parametresi almıyor. Etrafında karmaşık bir şeyler inşa etmeye ve/veya mtTkinter kullanmaya başlamadan önce temel bir Tkinter öğreticisi üzerinde çalışmanız gerektiğini düşünüyorum. Yanıtları bulamadığınız belirli sorularınız varsa, yeni bir soru oluşturun, ancak SO yorum'ta Tkinter temellerini öğretemiyorum. – abarnert

İlgili konular