2

I'm building a GTK GUI in Python and I need to get some data from the database which takes quite long, so the GUI freezes.

So I'm now using Threads to run the refreshing "in the background":

Thread(target=self.updateOrderList).start()

I have GUI class with alle relevant methods to manipulate the GUI. My solution work 80% of the time, but when it doesn't GTK crashed and it outputs this:

[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python3.6: ../../src/xcb_io.c:165: dequeue_pending_request:

The other times it works good, the data get loaded and its refreshing the gui.

edit: Sometimes I get this error:

Gdk-Message: 11:13:42.848: main.py: Fatal IO error 11 (Die Ressource ist zur Zeit nicht verfügbar) on X server :0

Sometimes I click the refresh button several times and it works, but then it doesn't at some point.

My main.py looks like this:

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject

import gui

GObject.threads_init()

# start gui
gui.Gui()
Gtk.main()

Any ideas whats happening here?

Markus

5
  • could be related to order in which threads run; try to ensure the GUI is fully initialised before the background thread starts putting requests into the GUI (to experiment, introduce a sleep statement on commencing the background thread) Commented Nov 4, 2019 at 10:12
  • I tried but it gets triggered on a button, so waiting doesn't solve the problem. Commented Nov 4, 2019 at 10:17
  • Relevant handling-gtk-objects-on-threads-in-python Commented Nov 4, 2019 at 11:27
  • @stovfl Thanks, might be a good solution. Do you know if it also possible to do this via signals/callbacks? Commented Nov 4, 2019 at 11:52
  • It's common sense to use GLib.idle_add(self._callback), see Possible solution for Threads Commented Nov 4, 2019 at 12:08

1 Answer 1

4

Okay, GTK3 is not threadsafe. So I changed the program logic - doing requests in a new thread, and handling the GUI manipulation in the GUI thread ONLY. So that means I have to emit a "requests done" signal to the event loop:

Creating a new signal and registering it:

GObject.signal_new("my-custom-signal", self.window, GObject.SIGNAL_RUN_LAST, GObject.TYPE_PYOBJECT,
                       (GObject.TYPE_PYOBJECT,))
self.window.connect("my-custom-signal", self.updateOrderListCallback)

So when I click a button, start a thread:

Thread(target=self.updateOrderListThread).start()

In that thread, do the calculations, and then emit the signal:

self.window.emit("my-custom-signal", None)

so than the callback will be called after the calculations/requests/whatever are done and it works!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.