Long running code in a signal handler

I have an app with an apply button with its ‘clicked’ signal connected to a method named on_apply. The problem is that on_apply method takes a few seconds to run and while it is running, the app becomes unresponsive.

To solve that problem, I wanted to show a modal window with a spinning circle so that the users know that work is being done. So, I thought why not do something like this

def on_apply(self, widget):
    win = Adw.Window(modal=True, transient_for=main_window)
    # Add some widgets to the window here
    win.show()

    # 'Apply' code goes here

    win.close()

But that doesn’t work. The new window does not show up, probably because it was going to show up after the signal handler was finished but it got closed right before that.

So, then I tried using Python’s concurrent.futures module like so

def on_apply(self, widget):
    win = Adw.Window(modal=True, transient_for=main_window)
    # Add some widgets to the window here
    win.show()

    def do_the_work():
        # 'Apply' code goes here
        win.close()

    from concurrent.futures import ThreadPoolExecutor
    executor = ThreadPoolExecutor(max_workers=1)
    executor.submit(do_the_work)

It seemed to work initially but then I noticed that I got following warning sometimes which I do not want.

(gdm-settings:12289): Gdk-WARNING **: 15:25:10.858: gdk_gl_context_make_current() failed

My question: how to handle code inside a signal handler that takes multiple seconds to run?

TLDR;

The code I want to run inside a signal handler takes a few seconds to run. How do I make it run in the background and show a dialog or window to the user asking them to wait for it to finish?

If you are in another thread and need to do anything with the UI - go back from there with Idle.add(). Never call GTK stuff from a different thread, that’s why you’re seeing the error.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.