0

I'm developing an application that manages a lot of objects inheriting from threading.Thread. For some some reasons, I created a user interface with the Tkinter library that would print the evolution of my objects. To communicate with my window, I have another thread that manages all the backend application and will transmit the data to the window.

But I'm struggling on a problem. My window still responsive but takes a huge amount of time to react. So I'm not able to see the results in real time. I tried to summarize my problem as follows:

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()

So my UI creates a bigThread object and start it when I press start button. The bigThread object will launches a hundred littleThread objects that will run an expensive computation function. As a result, my window still stuck until sometimes, there is kind of refreshment. I would be able to have enough refreshments or enough time allow to the window to make responsive time the shortest as possible.

(I already read related questions but mine's differ because the window still responsive but not enough)

Any idea how to do that? Thank's in advance for your help

Bucky
  • 65
  • 8
  • Read [whats-the-difference-between-update-and-update-idletasks](https://stackoverflow.com/questions/29158811/whats-the-difference-between-update-and-update-idletasks) – stovfl Dec 03 '18 at 08:18
  • Seems a little bit more reactive when calling update_idletasks() but do not fully solve the problem, but thank you – Bucky Dec 04 '18 at 05:56
  • Rethink about [limit-maximum-number-of-threads-running-at-once](https://stackoverflow.com/questions/19369724/the-right-way-to-limit-maximum-number-of-threads-running-at-once) – stovfl Dec 04 '18 at 08:03

0 Answers0