2013-02-04 96 views
12

當我打電話RuntimeError:螺紋主力是不是在主循環

self.client = ThreadedClient() 

在我的Python程序,我得到的錯誤

"RuntimeError: main thread is not in main loop"

我已經做了一些google搜索,但我做的錯誤莫名其妙...有人可以幫我嗎?

完整的錯誤:

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 

類:

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

從你的追蹤中,它看起來像你從其他地方創建的線程運行'workerGuiThread',而不是從主執行線程運行。我不是一位傳統知識專家,但是這個錯誤似乎表明這是不允許的(你需要使用主線程來調用TK函數,比如'after')。 – Blckknght

+0

請參閱[這個問題](http://stackoverflow.com/questions/3567238/i-need-a-little-help-with-python-tkinter-and-threading),[這個答案](http:// stackoverflow .com/a/10556698/908494)等等,瞭解在多線程程序中使用TkInter的一些細節。但簡短版本是:只在主線程中使用它,句號。 – abarnert

+0

嘿Blckknght。爲此我使用mtTkinter。 – user2040823

回答

17

你正在運行的線程的主界面循環,除了主線程。你不可以做這個。

文檔在一些地方提到了異常,Tkinter並不是非常安全的,但據我所知,從來沒有完全出來,並且說你只能從主線程與Tk交談。原因是事實有些複雜。 Tkinter本身線程安全的,但很難以多線程方式使用。最近的官方文件上,這似乎是this page

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…

(給出的樣本代碼不是很大,但它足以找出他們是在暗示什麼,做正確的事情。)

其實 Tkinter的一個線程安全的替代品,mtTkinter。而其實際的文檔說明情況還算不錯:

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.

我相信這是你看到什麼:你的Tkinter代碼線程1試圖窺視到主線程找到主迴路,和它不在那裏。

所以,這裏有一些選擇:

  • 做什麼Tkinter的文檔推薦和使用Tkinter的主線程。可能通過將當前的主線程代碼移動到工作線程中。
  • 如果您正在使用某個其他需要接管主線程的庫(例如twisted),它可能有辦法與Tkinter集成,在這種情況下,您應該使用該庫。
  • 使用mkTkinter來解決問題。

此外,雖然我沒有找到任何確切的重複這個問題,有一些相關的問題在SO上。有關更多信息,請參見this questionthis answer等等。

+0

嘿,abarnert。感謝您的回答。我用mtTkinter的選項。我的代碼正在運行(我的意思是沒有錯誤)。但是我看不到畫布...在日誌中我看到程序正在工作......只有沒有可視化。你看不到代碼@ https://github.com/wimhendrickx/Flocking/blob/master/bird_swarm.py。提前致謝。 – user2040823

+0

@ user2040823:爲什麼我看不到代碼,它是否在白色背景上的白色文本? :)無論如何,我會下載並看一看。 – abarnert

+0

@ user2040823:好的,這裏有幾個基本問​​題。首先,你不會在任何地方調用'root.mainloop()'。其次,你有像'doSomething'這樣的方法不需要'self'(而不是'staticmethod's)。第三,你的'Tkinter'事件處理程序沒有使用'event'參數。我想你需要通過一個基本的Tkinter教程,然後再嘗試構建一些複雜的東西,或者使用mtTkinter。如果您有任何具體問題無法找到答案,請創建一個新問題,但我無法在SO評論中教您Tkinter基礎知識。 – abarnert