ImTooMad
ImTooMad

Reputation: 9

Whenever i use xxx.join() it never works

Whenever i use xxx.join() it never works, eitehr just stops and doesnt carry on the rest of the code or crashes my program. in this case crashing my program. i usually make do without it, but for my current program i am trying to allow the client to wait for a message from the server, and i need .join() to allow this without crashing. new_message only crashes my program and doesnt allow the new gui to form. No errors come up in terminal, just crashes

        def email_verify_gui():
            # new gui
            email_entry.destroy()
            username_entry.destroy()
            createpassword_entry.destroy()
            confirmpassword_entry.destroy()
            invalid_passwords.destroy()
            invalid_boxes.destroy()
            next_button.destroy()

            S2.configure(text="Verify your email.")
            img2 = customtkinter.CTkImage(dark_image=Image.open("emailverify2.png"), size=(250, 175))
            subtitle = customtkinter.CTkLabel(master=frame_signup, text=("Complete the tab we opened "
                                                                         "so that we can verify your email."),
                                              text_color="#fff", font=("Century Gothic", 16), wraplength=300)
            subtitle.place(x=27, y=90)
            email_img = customtkinter.CTkLabel(master=frame_signup, image=img2, text="")
            email_img.place(x=35, y=130)

        def server_email():
            server_email_status = False
            client.send(("send email").encode())
            client.send(new_email.encode())
            print(new_email)
            file_path = "C:\\Users\\gunne\\PycharmProjects\\Playground\\email verification html.html"
            webbrowser.open(file_path, new=2)

        def new_message():
            while True:
                server_verify_message = client.recv(2048).decode()
                if server_verify_message:
                    print(server_verify_message)
                    break


        thread_email_verify_gui = threading.Thread(target=email_verify_gui)
        thread_server_email = threading.Thread(target=server_email)
        thread_new_message = threading.Thread(target=new_message)
        print("Threads Established")

        thread_email_verify_gui.start()
        #thread_email_verify_gui.join()
        print("STAGE 1")

        thread_server_email.start()
        #thread_server_email.join()
        print("STAGE 2")

works without the .join() but crashes my program still for as long as i use new_message()

Upvotes: 0

Views: 8863

Answers (2)

jonathan
jonathan

Reputation: 54

I can see 2 issues :

  • Calling .join() on a thread that performs blocking operations will freeze the main thread, causing the GUI to become unresponsive, if this is what you mean by "crash"
  • tkinter (and customtkinter) is not thread-safe. Modifying GUI elements from any thread other than the main thread can cause crashes.

Start threads without .join()

threading.Thread(target=server_email).start()
threading.Thread(target=new_message).start()

Communicate with the Main Thread Using a Queue

import queue
import threading

message_queue = queue.Queue()

def new_message():
    server_verify_message = client.recv(2048).decode()
    if server_verify_message:
        message_queue.put(server_verify_message)

def check_for_messages():
    try:
        while True:
            message = message_queue.get_nowait()
            print(message)
    except queue.Empty:
        pass
    root.after(100, check_for_messages)

check_for_messages()

threading.Thread(target=new_message).start()

Upvotes: 1

Mougnou
Mougnou

Reputation: 188

You will need to use ThreadPoolExecutor to achieve this basicaly it's allow you to add a call back on a thread.

from concurrent.futures import ThreadPoolExecutor 
def email_verify_gui():
            # new gui
            email_entry.destroy()
            username_entry.destroy()
            createpassword_entry.destroy()
            confirmpassword_entry.destroy()
            invalid_passwords.destroy()
            invalid_boxes.destroy()
            next_button.destroy()

            S2.configure(text="Verify your email.")
            img2 = customtkinter.CTkImage(dark_image=Image.open("emailverify2.png"), size=(250, 175))
            subtitle = customtkinter.CTkLabel(master=frame_signup, text=("Complete the tab we opened "
                                                                         "so that we can verify your email."),
                                              text_color="#fff", font=("Century Gothic", 16), wraplength=300)
            subtitle.place(x=27, y=90)
            email_img = customtkinter.CTkLabel(master=frame_signup, image=img2, text="")
            email_img.place(x=35, y=130)

        def server_email():
            server_email_status = False
            client.send(("send email").encode())
            client.send(new_email.encode())
            print(new_email)
            file_path = "C:\\Users\\gunne\\PycharmProjects\\Playground\\email verification html.html"
            webbrowser.open(file_path, new=2)

        def new_message():
            while True:
                server_verify_message = client.recv(2048).decode()
                if server_verify_message:
                    print(server_verify_message)
                    break

        
        executor = ThreadPoolExecutor(max_workers=3)

        future = executor.submit(email_verify_gui)
        future.add_done_callback(lambda x:server_email)
        future.add_done_callback(lambda x:new_message)
        

For more information -> https://superfastpython.com/threadpoolexecutor-in-python

Upvotes: 0

Related Questions