title: Stop pygtk GUI from locking up during long-running process
body: <p>I have a process that will take a while (maybe a minute or two) to complete. When I call this from my pygtk GUI the window locks up (darkens and prevents user action) after about 10 seconds.</p>
  
  <p>I'd like to stop this from happening, but I'm not sure how. I thought multithreading would be the answer, but it doesn't seem to be working. I've tried two different methods I found online. First, I modified <a href="http://faq.pygtk.org/index.py?file=faq20.006.htp&amp;req=show" rel="nofollow noreferrer">this FAQ</a> to take a long running function. Secondly I tried using threading.Thread directly like in <a href="https://stackoverflow.com/a/686045/817630">this answer</a>, but that also locks up.</p>
  
  <p>My two samples are below. I'm new to multithreading, so maybe it's not the solution I'm looking for. I'm basically just trying to keep the GUI from locking up so I can update with a progress bar and let the user use a cancel button.</p>
  
  <pre><code>#Sample 1
  import threading
  import time
  import gobject
  import gtk
  
  gobject.threads_init()
  
  class MyThread(threading.Thread):
      def __init__(self, label, button):
          super(MyThread, self).__init__()
          self.label = label
          self.button = button
          self.counter = 0
          button.connect("clicked", self.on_button_click)
          self.quit = False
  
      def update_label(self, counter):
          self.label.set_text("Counter: %i" % counter)
          time.sleep(20)
          return False
  
      def on_button_click(self, widget):
          self.counter += 1
          gobject.idle_add(self.update_label, self.counter)
  
  window = gtk.Window()
  label = gtk.Label()
  box = gtk.VBox()
  button = gtk.Button("Test")
  box.pack_start(label)
  box.pack_start(button)
  window.add(box)
  window.show_all()
  window.connect("destroy", lambda _: gtk.main_quit())
  thread = MyThread(label, button)
  thread.start()
  
  gtk.main()
  thread.quit = True
  
  #####################################
  #Sample 2
  
  from threading import Thread
  import time
  import gobject
  import gtk
  
  class Test():
      def __init__(self):
          self.counter = 0
          self.label = gtk.Label()
          button = gtk.Button("Test")
  
          window = gtk.Window()
          box = gtk.VBox()
          box.pack_start(self.label)
          box.pack_start(button)
          window.add(box)
  
          window.connect("destroy", lambda _: gtk.main_quit())
          button.connect("clicked", self.on_button_click)
          window.show_all()
  
      def update_label(self, counter):
          self.label.set_text("Counter: %i" % counter)
          time.sleep(20)
          return False
  
      def on_button_click(self, widget):
          self.counter += 1
          thread = Thread(target=self.update_label, args=(self.counter,))
          thread.start()
          while thread.is_alive():
              pass
          thread.stop()
  
  test = Test()
  gtk.main()
  </code></pre>