首页 > 解决方案 > 如何在运行大量后端线程时管理 Tkinter 窗口响应性

问题描述

我正在开发一个应用程序来管理许多从 threading.Thread 继承的对象。由于某些原因,我使用 Tkinter 库创建了一个用户界面,可以打印我的对象的演变。为了与我的窗口通信,我有另一个线程来管理所有后端应用程序并将数据传输到窗口。

但我正在努力解决一个问题。我的窗口仍然响应,但需要大量时间才能做出反应。所以我无法实时看到结果。我试图将我的问题总结如下:

from threading import Thread
from tkinter import *
from time import sleep
from random import random

class UItest(Tk):

    def __init__(self):
        Tk.__init__(self)

        # Graphic elements of the window
        self.startButton =      Button(master=self,width=3,text="Start/stop",command=self.start_stop)
        self.title =            Label(master=self,text="Nb of iterations")
        self.name_1 =           Label(master=self, text="Thread 1 :")
        self.name_2 =           Label(master=self, text="Thread 2 :")
        self.name_3 =           Label(master=self, text="Thread 3 :")
        self.name_4 =           Label(master=self, text="Thread 4 :")
        self.name_5 =           Label(master=self, text="Thread 5 :")
        self.value_1 =          Label(master=self, text="0")
        self.value_2 =          Label(master=self, text="0")
        self.value_3 =          Label(master=self, text="0")
        self.value_4 =          Label(master=self, text="0")
        self.value_5 =          Label(master=self, text="0")

        self.startButton.grid(row=0,sticky='nsew')
        self.title.grid(row=1, sticky='nsew')
        self.name_1.grid(row=2, column=0, sticky='w')
        self.value_1.grid(row=2, column=1, sticky='w')
        self.name_2.grid(row=3, column=0, sticky='w')
        self.value_2.grid(row=3, column=1, sticky='w')
        self.name_3.grid(row=4, column=0, sticky='w')
        self.value_3.grid(row=4, column=1, sticky='w')
        self.name_4.grid(row=5, column=0, sticky='w')
        self.value_4.grid(row=5, column=1, sticky='w')
        self.name_5.grid(row=6, column=0, sticky='w')
        self.value_5.grid(row=6, column=1, sticky='w')

        # Computing elements
        self.computingThread=bigThread()
        self.computingThread.connectToUItest(self.getValues)
        self.state = 0

        self.mainloop()

    def getValues(self,val1,val2,val3,val4,val5):
        self.value_1.config(text=val1)
        self.value_2.config(text=val2)
        self.value_3.config(text=val3)
        self.value_4.config(text=val4)
        self.value_5.config(text=val5)

    def start_stop(self):
        if self.state==0:
            self.computingThread.start()
            self.state=1
            print("start")
        else:
            self.computingThread.exitflag=1
            print("stop")

class bigThread(Thread):

    def __init__(self):
        Thread.__init__(self)
        self.exitflag=0
        self.thread_list=[]
        for i in range(100):
            thread=littleThread()
            thread.ID=i
            self.thread_list.append(thread)

    def connectToUItest(self, func):
        self.updateUI = func

    def run(self):
        for i in range(100):
            self.thread_list[i].start()
        while self.exitflag==0:
            self.updateUI(self.thread_list[0].nb_iteration,
                          self.thread_list[1].nb_iteration,
                          self.thread_list[2].nb_iteration,
                          self.thread_list[3].nb_iteration,
                          self.thread_list[4].nb_iteration)
            sleep(0.01)
        for i in range(100):
            self.thread_list[i].exitflag = 1

class littleThread(Thread):

    def __init__(self):
        Thread.__init__(self)
        self.nb_iteration=0
        self.exitflag=0
        self.ID=0

    def run(self):
        while self.exitflag==0:
            self.nb_iteration+=1
            self.doExpensiveStuff()
            sleep(random()*3)
        print("Thread", self.ID, "exits")


    def doExpensiveStuff(self):
        size=200
        a = []
        b = []
        for i in range(1):
            for row_index in range(size):
                a_row=[]
                b_row=[]
                for col_index in range(size):
                    a_row.append(random())
                    b_row.append(random())
                a.append(a_row)
                b.append(b_row)
        return expensiveProduct(a,b)

def expensiveProduct(a,b):
    for i in range(len(a)):
        for j in range(len(a)):
            a[i][j]=a[i][j]*b[i][j]
    return a


App = UItest()

所以我的 UI 创建了一个 bigThread 对象并在我按下开始按钮时启动它。bigThread 对象将启动一百个 littleThread 对象,这些对象将运行昂贵的计算函数。结果,我的窗户仍然卡住,直到有时,有一种清爽。我将能够有足够的茶点或足够的时间允许窗口使响应时间尽可能短。

(我已经阅读了相关问题,但我的不同,因为窗口仍然响应但还不够)

知道怎么做吗?在此先感谢您的帮助

标签: pythonmultithreadingtkinter

解决方案


推荐阅读