I am using the easygui library to make a simple interface for my program.
In the program, I need to start a process that takes time and the user can cancel it if he is tired of waiting.
Here is a minimal example code:
import easygui as eg
import threading
import time
stop_process_flag = False
def try_connection():
global stop_process_flag
while True:
time.sleep(1)
if stop_process_flag:
return False
# "foo" will eventually connect (return a True value)
connected = foo()
if connected:
return True
def end_connection():
global stop_process_flag
stop = eg.msgbox('Click ok to stop process before completion')
# code does not reach here if the user does not click ok in the easygui box
if stop:
stop_process_flag = True
# create threads
process_thread = threading.Thread(target=try_connection)
monitor_thread = threading.Thread(target=end_connection)
# start threads
process_thread.start()
monitor_thread.start()
# Wait the process to finish. It can happen due to successful completion or user cancellation
process_thread.join()
# Check if the user has clicked the ok button and ended the thread
if monitor_thread.is_alive():
# Here i need to stop the thread to close the eg.msgbox
# code continues
I want to close the msgbox if the connection is successful and the user never clicked ok to cancel the connection.
The problem is that if the user never clicks ok, the msgbox will never return and the code will never reach any line after the msgbox line.
So I can't even add a flag to the end_connection function because there will never be a chance for the function to check it.
How can I kill this monitor_thread "gracefully"?
Or, is there another way to achieve the desired result?
Let me know if you need more code or information to understand something. The actual code has a lot of unnecessary things that may draw attention from the actual problem.
You could use the multiprocessing
module instead of threading
because it allow you to terminate a process whereas thread dont do it properly.
Here is the modified code:
import easygui as eg
import multiprocessing
import time
stop_process_flag = multiprocessing.Value('b', False)
def try_connection(stop_process_flag):
while True:
time.sleep(1)
if stop_process_flag.value:
return False
connected = foo()
if connected:
return True
def end_connection(stop_process_flag):
stop = eg.msgbox('Click ok to stop process before completion')
if stop:
with stop_process_flag.get_lock():
stop_process_flag.value = True
process_process = multiprocessing.Process(target=try_connection, args=(stop_process_flag,))
monitor_process = multiprocessing.Process(target=end_connection, args=(stop_process_flag,))
process_process.start()
monitor_process.start()
process_process.join()
if monitor_process.is_alive():
monitor_process.terminate()
monitor_process.join()