python - 如何在运行大量后端线程时管理 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 对象,这些对象将运行昂贵的计算函数。结果,我的窗户仍然卡住,直到有时,有一种清爽。我将能够有足够的茶点或足够的时间允许窗口使响应时间尽可能短。
(我已经阅读了相关问题,但我的不同,因为窗口仍然响应但还不够)
知道怎么做吗?在此先感谢您的帮助
解决方案
推荐阅读
- continuous-integration - [gitlab ci]:如何等待一个工作,只有这个工作已经开始,但如果它被跳过则不行
- php - 如何根据数据库的结果显示铭文?
- c++ - 为什么 C++ 允许返回 ifstream 对象?
- r - 从 R 中的浏览器/用户代理数据检测设备(移动设备、平板电脑和 PC)
- excel - 如何更新用户表单中的条目?
- javascript - 有没有办法让我在这个函数中封装异步/等待处理?
- python - 在另一个视图函数中包含一个带有渲染的函数
- node.js - 你应该在同一个端口上创建 Express 和 React 吗?
- javascript - 加载包含数组的 URL/API 的问题 - javascript/p5js
- c# - 使用实体进行数据验证