PDA

View Full Version : Purging the queue in a Qt::QueuedConnection



Eos Pengwern
3rd November 2010, 01:51
I have an application where a QThread generates data which it sends to the main GUI thread via a signal/slot connection. Like all such connections, it defaults to Qt::QueuedConnection so that each signal from the thread is stored in a queue until the GUI is ready to act on it.

I have a problem, though: sometimes, the thread sends data much more rapidly than the GUI can display it, with the result that a noticeable time delay builds up: I've seen cases where the GUI is still laboriously updating itself several seconds after the thread has stopped sending data.

A solution to the problem would be for the thread to be able to purge the signal queue before placing a new signal on it, so that any out-of-date signals stuck in the queue would be replaced by the new signal. Is there a way of doing this?

In another application where I had the opposite problem (i.e. the GUI sent data more quickly than the thread could handle it), I implemented a manual queue using a QList of 'signal structs' and it worked perfectly. Each time the GUI had data to send, it would check through the QList and remove any entries which were out-of-date, before adding its new data to the end of the queue: inside a mutex of course. The 'run' function in the QThread would then just read the entry at the front of the queue each time it went through its loop.

However, in this case I can't see a way of implementing a manual queue because the GUI's event loop is inaccessible, unlike the 'run' loop in a QThread. If the signal queue can't be purged and a manual queue can't be read, is there any other way of tackling this problem?

Many thanks,
Stephen.

Added after 11 minutes:

Just had an idea which I'll try in the morning if no-one suggests anything better...
1. Implement a manual queue as before.
2. Have the GUI update routine emit a finished() signal when it has completed an update.
3. Connect the finished() signal to a slot function that examines the queue and sends the data at the head of it back to the GUI update routine.

Farris
3rd November 2010, 11:08
You could use a direct connection slot to set some kind of indicator in the gui thread(remember to mutex this indicator) and have the gui thread slot with the filled queue could check the indicator to see if it should process the queued elements or discard them. Taking this even further you could also add a sequence number to each element and have the indicator represent the "earliest eligeble sequence number" and the gui thread could discard any elements with a older sequence number.

Eos Pengwern
3rd November 2010, 17:32
I managed to implement the technique which I had outlines earlier, and it worked well but all it showed was that in fact the bottleneck was elsewhere. I'm currently trying to get to the bottom of some very strange behaviour with QByteArray...

Added after 37 minutes:

QByteArray was in fact behaving perfectly well; I was just trying to parse a sting which had '\r' (a carriage return) as its first character, and didn't take proper account of this.