wxpython Python knowing when threads have finished -> stuck

100 Views Asked by At

I'm continuing with my program of doing computer checks. It's WXPYTHON based.

The program shows an interface with labels and a "run" button when the button is clicked it launches the "doCheck" function in the mainFrame class

the doCheck then launches all the threads:

Thread1 = computerCheck()
Thread2 = countProcess()
Thread3 = findProcess()
Thread4 = findProtection()
Thread5 = bitlockerCheck()

Thread1.start()
Thread2.start()
Thread3.start()
Thread4.start()
Thread5.start()

The threads are doing some WMI checks etc and report by using pubsub.sendMessage() the MainFrame class has a listener function which updates the GUI labels when a message is received.

so far so good! allis working well. But now I want to know when all the threads which are launched have finished. This is where the problem comes in... If I use the join() on the threads, the PUBSUB GUI updating is not working until all threads are finished. If I use a while statement in the doCheck function that loops for "isAlive()" it basically does the same, waiting for everything to end. Again, PUBSUB is halted as well...

So I'm stuck here. The program works fine so far, but now I need to launch a next step when all checks are done / completed but I can't figure out how to accomplish this without blocking the runtime updates by PUBSUB....

a snippet of the actual threads:

class findProcess(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        my_object = dict(status='Running', result='')
        wx.CallAfter(pub.sendMessage, 'testListener', message=3,arg2=my_object)

ps. the message argument is used to know which of the labels shall be updated...

Any suggestions? I'm fine with posting more code when needed.

Thanks

1

There are 1 best solutions below

0
On

One of the solutions could be:

Start another thread that will do join, and when all threads are joined, post a message to the main thread. Upon that message you know that the threads are finished and you can go on with the work...

Or, this one is slightly hackish: Make a function that will check the is_alive of all threads every 100 ms. Something like this:

def check_threads_finished(self):
    for i in self.my_threads:
        if i.is_alive():
            wx.CallLater(100, self.check_threads_finished)
            return
    # finished
    self.do_whatever_is_needed_after_threads_finished()