Hi list,
recently I started to work on an application [1] which makes use of the Tkinter
module to handle interaction with the user.  Simply put, the app is a text
widget displaying a file filtered by given criteria, with a handy feature that
the window is raised each time a new line is added to the widget.

The application mainly consists of three threads:  the first one, the file
processor, reads the file, filters the lines of interest, and pushes them into
a shared queue (henceforth `lines_queue`);  the second one, the gui_updater,
pops elements from `lines_queue`, and schedule GUI updates using the
`after_idle` method of the Tkinter module;  finally the last one, the worker
spawner, receives commands by the gui (by means of a shared queue,
`filters_queue`), and drives the application, terminating or spawning new
threads.

For example, let's see what happens when you start the application, fill the
filter entry and press Enter button:
1 the associated even handler is scheduled (we should be inside the Tkinter
 mainloop thread), and the filter is pushed into `filters_queue`;
2 the worker spawner receives the new filter, terminate a possibly running
 working thread, and once done, create a new file processor;
3 the file processor actually processes the file and fills the `lines_queue`
 with the lines matching given filter;
4 the gui updater schedules GUI updates as soon as items are pushed into
 `lines_queue`
5 Tkinter mainloop thread updates the gui when idle

What happens when the main window is closed?  Here is how I implemented the
graceful shutdown of the app:
1 a quit event is scheduled and a _special_ message is pushed into both
 `filter_queue` and `lines_queue`
2 the gui updater threads receives the _special_ message, and terminates
3 the worker spawner receives the message, terminates the working thread and
 interrupts her execution.
4 Tk.quit() is called after the quit event handler, and we finally quit the
 mainloop

Honestly speaking, I see no issues with the algorithm presented above;  however,
if I close the window in the middle of updates of the text widget, the
applications hangs indefinitely.  On the other hand, everything works as
expected if I close the app when the file processor, for example, is waiting for
new content to filter.

I put some logging messages to analyze the deadlock (?!), and noticed that both
the worker spawner and the file processor are terminated correctly.  The only
thread still active for some strange reasons, is the gui updater.

Do you see anything wrong with the description presented above?  Please say so,
because I can't figure it out!


Regards,
Matteo

-- 
http://www.matteolandi.net
_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss@python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss

Reply via email to