Search code examples
pythonpyqtqthread

PyQt Confirmation Finishing of Multiple QThreads


I created a GUI tool with Qt Creator and Python. In the GUI the user would select types of the shapefile he/she wants to generate. The script stores the selection in a list. Generating of each type of shapefile is handled by separate QThreads. Each QThread would print some messages like "Processing AAA....". The "run" button function would then do:

if optionA in selection_list:
    QThreadA.start()
if optionB in selection_list:
    QThreadB.start()
if optionC in selection_list:
    QThreadC.start()

Now I am trying to have the GUI pop up a window when all QThreads finish. I found it here https://riverbankcomputing.com/pipermail/pyqt/2007-May/016026.html that QThread.wait() works the same as thread.join(), and I am trying to utilize it.

I cannot do

if optionA in selection_list:
    QThreadA.start()
if optionB in selection_list:
    QThreadB.start()
if optionC in selection_list:
    QThreadC.start()

QThreadA.wait()
QThreadB.wait()
QThreadC.wait()
print("All set")

Since sometimes not all QThreads would be running.

But if I do

if optionA in selection_list:
    QThreadA.start()
if optionB in selection_list:
    QThreadB.start()
if optionC in selection_list:
    QThreadC.start()

if optionA in selection_list:
    QThreadA.wait()
if optionB in selection_list:
    QThreadB.wait()
if optionC in selection_list:
    QThreadC.wait()
print("All set")

Not only does this look dumb, when I hit "run" button, I would also get

"All set"
"Processing AAA..."
"Processing BBB..."
"Processing CCC..." 

The messages appear altogether when apparently everything finished, instead of what I was hoping to see:

"Processing AAA..."
some time passed...
"Processing BBB..."
some more time passed...
"Processing CCC..."
some more time passed...
"All set"

What is the order of the things that happen here? And this basically makes the messages useless as the user would only see them when everything finishes at last.

Could use some help on how to reconstruct the functions.

Edit: According to @Nimish Bansal's recommendation, I come up with this:

dict = {optionA: QThreadA, optionB: QThreadB, optionC: QThreadC}
for option in selection_list:
    dict[option].start()

to avoid the previous stupid "if"s, but I still have not found a effective way to conclude all the threads, since:

for options in selection_list:
    dict[option].wait()

does not seem to work, due to the .wait() would pause the for loop I guess?


Solution

  • def run_fun(a):
        print("processing",a)
        time.sleep(2)
    
    import threading
    A=threading.Thread(target=run_fun,args=('aaa',))
    B=threading.Thread(target=run_fun,args=('bbb',))
    C=threading.Thread(target=run_fun,args=('ccc',))
    
    
    
    
    def join_threads(listi):
        for j in listi:
            j.join()
        print("ALL set","open your gui here")
    
    
    
    A.start()
    B.start()
    C.start()
    threading.Thread(target=join_threads,args=([A,B,C],)).start()
    

    OUTPUT

    processing aaa

    processing bbb

    processing ccc

    ALL set open your gui here