PDA

View Full Version : How to "inform" right thread that something has happened with the interface?



kremuwa
9th July 2010, 10:18
Hello,

I am working on a p2m client, and I'm using separate thread for each download - when an user adds a file to download, a new thread is created and the download starts in this thread. That's really cool, the GUI is responding all the time although I use waitFor... functions but there is one problem I can't solve - if, for example an user wants to pause the process of downloading or to stop and remove currently downloaded segments at all he/she selects the appropriate download (represented as a single row) and clicks a button responsible for such an action. And now, how to "inform" the right thread that it should pause/stop the downloading process? How to do it in a nice way?

Thanks in advance,
Michael

tbscope
9th July 2010, 10:34
Why do you make it yourself so difficult by using threads?
Did you know that you can have a perfectly responsive user interface without using threads?

Anyway, use signals and slots. You probably will need to rewrite your threading code if you followed the Qt documentation.
http://labs.trolltech.com/blogs/2006/12/04/threading-without-the-headache/
http://labs.trolltech.com/blogs/2010/06/17/youre-doing-it-wrong/

If I may give you some advice: do not use threads for device IO operations like reading files or sending something over a socket UNLESS it is required if the device is blocking. Sockets are not blocking when you don't use the blocking functions.
Only use a thread if you want to decode or encode some data and even this can be made asynchronous.

kremuwa
9th July 2010, 21:08
One person here told me to use threads when I was asking about how to have responding interface. Ok, so what can I use instead these blocking functions?

tbscope
10th July 2010, 07:17
There are two ways to use sockets.

1. Synchronous, also called blocking.
If you use synchronous sockets, your program halts till the socket returns from a function. It's only used when you have hardware that must be used synchronously (there isn't a lot of hardware that requires this).
You send or receive something to or from a connected socket and then wait till it responds or finished. The waiting part is a problem. Therefor you want to put synchronous code into a separate thread.

2. Then there is asynchronous, also called non blocking
The way these sockets work is very different. Instead of sending a huge blob of data at once, it splits the data into managable packages. Every time the read buffer gets, lets say, 100 kB of data, it emits a readyRead signal.
You can connect a slot to the readyRead signal and read the buffer. Since the buffer is filled whenever there's data available and the signal is emitted whenever the buffer is full, the program doesn't have to wait, it happens in the background without blocking everything else. The socket receives a few bytes and adds them to the buffer, it doesn't wait for the bytes as it gets notified when they are there.

This comes with a few inconveniences.
1. You do need to reassemble the packages. Example: if you send a jpg that is 200kB big and the packages are 50kB big, you need to append the data till there's no more data. This can be tricky if you do not know the size of the data.
2. You need to implement your own time-out timer.

The conveniences are that you don't need to use threading as the program has lots of time in between receiving and handling the packages to handle all the other events.

As with threading, I do not want to say it is bad to use it. Only that it is more tricky although it seems more easy.
Example: QThread is not what you think it is.

Most people think that QThread, the class itself, is a separate thread. Far from it. It should be seen as a thread manager that lives in the main thread.
Yes, the run() function does run the code inside that function in another thread.

The problem comes when you want to use signals and slots to inform the main thread of progress and errors etc...
Most people define their signals and slots in the QThread class. This works fine. BUT, these signals and slots are called inside the main thread because QThread lives in the main thread, it's not a separate thread.
This in turn can lead to errors and faulty logic.

The way to solve this is to actually run a QObject in another thread, instead of just the code in the run() function.
Therefor the moveToThread function of the object is used. If you create an object with signals and slots and then move the complete object to a new thread, these signals and slots (of the object itself) are called inside the new thread.
The QThread itself acts as a translator or manager between the signals and slots of your object in the new thread and the signals and slots in the main thread.

In short:
I prefer not to use threads for socket communication. I always use the readyRead() signal

kremuwa
10th July 2010, 09:44
Thanks a lot for your effort, I have read your post carefully as well as the articles you sent in the previous message. I'd like to ask one more question - what is "thread event loop" - is it an infinite loop that waits for some signals to do appropriate slots?

wysota
10th July 2010, 23:00
One person here told me to use threads when I was asking about how to have responding interface.
Then go back to that thread and tell the guy to stop spreading incorrect solutions.

You can read this article too: Keeping the GUI Responsive.