How to terminate a thread on Window 'X'

In a normal wxPython application, I start a thread before calling app.MainLoop(). The thread runs an infinite loop, listening on on database events (using Postgres LISTEN/NOTIFY). When there is an event, I update my wxPython main panel. Simple enough.

I also have an EXIT button bound to an exit handler. When I push the button, it generates an EVT_BUTTON event which in turn calls the exit handler, which tells the thread to terminate and destroys all windows. Everything terminates nicely.

But when I press the Windows ‘X’ button to close terminate, I know it should generate an EVT_CLOSE event which I can use to close everything.

But it does not; the application hangs.

From what I have read in the online sources, EVT_CLOSE is not generated because my thread is running. Kind of a catch-22! as far as I know, the only thing that would tell me that the application is closing in this case is the EVT_CLOSE event, which is not being issued.

Does anyone have a solution for this kind of thing?

EVT_CLOSE is generated anyway. The presence of the other thread is not a problem for EVT_CLOSE, I’ve practised it. The only point is that the application won’t terminate unless you join the other thread. Check if you bind (map) your on_lose function, or how do you call it.

UPD: on_close function

Try marking this extra tread as daemon tread.

Niki

···

On 29.10.2016 23:20, R. Miranda wrote:

In a normal wxPython application, I start a thread before calling
app.MainLoop(). The thread runs an infinite loop, listening on on
database events (using Postgres LISTEN/NOTIFY). When there is an event,
I update my wxPython main panel. Simple enough.

I also have an EXIT button bound to an exit handler. When I push the
button, it generates an EVT_BUTTON event which in turn calls the exit
handler, which tells the thread to terminate and destroys all windows.
Everything terminates nicely.

But when I press the Windows 'X' button to close terminate, I know it
should generate an EVT_CLOSE event which I can use to close everything.

But it does not; the application hangs.

From what I have read in the online sources, EVT_CLOSE is not generated
because my thread is running. Kind of a catch-22! as far as I know, the
only thing that would tell me that the application is closing in this
case is the EVT_CLOSE event, which is not being issued.

Does anyone have a solution for this kind of thing?

Thanks Michael, I’ll give it a shot.

UPDATE after input by Michael:

That did the job. I created a daemon thread and then issued a non-blocking join(1) call to ensure proper termination of both main application and its thread. Nikki later advised making a daemon thread, but I had already done that (so confirming that I did the right thing). Thanks to Michael and Nikki for your helpful advice.

···

On Monday, October 31, 2016 at 3:48:58 PM UTC+1, R. Miranda wrote:

In a normal wxPython application, I start a thread before calling app.MainLoop(). The thread runs an infinite loop, listening on on database events (using Postgres LISTEN/NOTIFY). When there is an event, I update my wxPython main panel. Simple enough.

I also have an EXIT button bound to an exit handler. When I push the button, it generates an EVT_BUTTON event which in turn calls the exit handler, which tells the thread to terminate and destroys all windows. Everything terminates nicely.

But when I press the Windows ‘X’ button to close terminate, I know it should generate an EVT_CLOSE event which I can use to close everything.

But it does not; the application hangs.

From what I have read in the online sources, EVT_CLOSE is not generated because my thread is running. Kind of a catch-22! as far as I know, the only thing that would tell me that the application is closing in this case is the EVT_CLOSE event, which is not being issued.

Does anyone have a solution for this kind of thing?

Acually, you’ve did it wrong, but in works at your side. In theory you have to do ONE of to options:

  1. Make daemon thread, and then you don’t need join at all.

  2. Make ordinary thread. Perhaps your thread is doing something in an endless loop. Make a thread-safe variable “stop_flag”. The thread should check it from time to time. When stop_flag is set to true, the function that is running in a thread must return. Finally
    in the clean-up code
    inside you main (GUI) thread, your do:
    stop_flag=True
    thread.join()
    note: this is a blocking join.