2016-05-03 44 views
2

我有這個「遊戲的東西」,我一直在努力。它完美地工作,除非在完成遊戲後關閉GUI時,它會繼續在後臺運行(就像內存泄漏一樣,即使「真實」的內存泄漏不會以這種方式工作)。使用線程和tkinter時的內存泄漏

這個遊戲運行(或者在理論上它應該)在兩個線程,一個用於GUI,另一個是遊戲本身,經過一番研究,我發現了,我可以用我的根插件的.protocol()方法執行raise SystemExit確保GUI關閉時所有線程都被終止。但它似乎沒有工作,我不知道爲什麼。這裏的代碼:

# -*- coding: UTF-8 -*- 
from tkinter import Tk, Label, Entry, Button, W, E, END 
from threading import Thread 
from random import randint 
class GUI(Thread): 
    tentativas = [] 
    def __init__(self): 
     Thread.__init__(Thread) 
     self.start() 
     self.valor = randint(0, 100) 
     self.vidas = 6 
     self.venceu = False 
     self.entry, self.aux = -128, -128 
     while self.vidas > 0: 
      self.vidas -= 1 
      while True: 
       if self.entry != self.aux: 
        break 
      self.aux = self.entry 
      if self.entry == self.valor: 
       self.txt01.config(text = "Congrats, you won!", fg = "green") 
       self.venceu = True 
       self.txt02.config(text = '') 
       break 
      elif self.entry > self.valor: 
       self.txt01.config(text = 'Too big, try again.') 
      else: 
       self.txt01.config(text = 'Too small, try again.') 
      self.txt02.config(text = str(self.vidas) + ' Chances restantes.') 
     if self.venceu != True: 
      self.txt01.config(text = 'You ran out of lives, game over!') 
      self.txt02.config(text = 'The number was ' + str(self.valor) + '.') 
    def run(self): 
     self.root = Tk() 
     self.root.title("Lottery") 
     self.txt00 = Label(self.root, text = "Welcome, insert a number ranging from 0 to 100:") 
     self.txt00.grid(sticky = W, columnspan = 4) 
     self.txt01 = Label(self.root, text = " ") 
     self.txt01.grid(row = 1, column = 0, columnspan = 4, sticky = W) 
     self.txt02 = Label(self.root, text ="6 Tentativas restantes.") 
     self.txt02.grid(row = 4, columnspan = 2, sticky = E) 
     self.inp00 = Entry(self.root) 
     self.inp00.grid(row = 2,columnspan = 2,column = 1,sticky = W) 
     self.but00 = Button(self.root, text = "Try!", command = self.chutar) 
     self.root.bind("<Return>", self.chutar) 
     self.but00.grid(row = 2, column = 3) 
     self.root.protocol("WM_DELETE_WINDOW", self.killGUI) 
     self.root.mainloop() 
    def chutar(self, args = None): 
     self.pular = True 
     try: 
      self.chute = int(self.inp00.get()) 
     except ValueError: 
      self.txt01.config(text = "Invalid entry, try again!", fg = "red") 
      self.pular = False 
     finally: 
      self.inp00.delete(0, END) 
     if self.pular: 
      if self.chute in range(101) and self.chute not in self.tentativas: 
       self.entry = self.chute 
       self.tentativas.append(self.entry)  
      else: 
       self.var = "Invalid entry, try again!" 
       self.txt01.config(text = self.var, fg = "red") 
    def killGUI(self): 
     raise SystemExit 
k = GUI() 

我真的不知道爲什麼「killGUI」函數不工作,請幫助我!

回答

0

(據我所知的Tkinter是不是線程安全的。這可能會導致這個問題。因此,使用與Tkinter的線程是不是一個好主意。我甚至不能確定你真的需要多線程這一點。)

編輯:似乎你只是用這個殺死你的childthread,主線程仍在運行。

但是要解決你的問題,一種方法是強制 - 「殺死」整個工藝流程。所有你需要的是你的腳本pid和一個子進程函數。試試這個代碼在你killGUI

def killGUI(self): 
    try: 
     subprocess.call(['taskkill', '/F', '/T', '/PID', str(os.getpid())]) 
     print("Process killed: %s " % str(os.getpid())) 
    except Exception as ex: 
     print(ex) 

這會殺了你的線程是肯定的。