PDA

View Full Version : QMessageBox and threads



vfernandez
5th February 2006, 12:58
I'm developing a project that connects through SSH to download some config files, parse them and allow the user to modify them. For the SSH connection I'm using libssh (http://0xbadc0de.be/wiki/doku.php?id=libssh:libssh) in a worker thread. During the stablishment of the connection (which takes place in the worker thread) sometimes I need to ask the user if he wants to accept the host key. So I wanted to emit a signal from the worker thread and connect it to the GUI thread so that it calls QMessageBox::question() and returns the value (a boolean) to the worker thread, which is meanwhile waiting for the reply of the GUI thread. But I have some problems. The first one is with signal/slots you can't return a value. Ok, I can pass a pointer to the variable and modify it from the GUI thread and since the worker thread is waiting for the GUI thread, I don't need to use a mutex. But the problem is when I emit the signal, the worker thread continues the execution instead of waiting for the reply as if it was a normal function call (but across threads). I could make the worker thread sleep and wake it up from the GUI thread after we get the answer from the user, but I don't think that's a good idea because if the signal was not connected to any slot the worker thread would sleep forever and I would like to keep my code as clean as possible, having a default value for the boolean and trying to modify it if there's something connected to the signal, otherwise taking the default value. Any idea on how to implement this?

wysota
5th February 2006, 14:48
You can use custom events:
1. Send a custom event to the main thread and block the worker thread using a wait condition or a semaphore.
2. In the main thread handle the custom event, showing the requester
3. After you receive a response, wake up the worker thread and pass a response from the requester to it (remember to store the response first and then wake up the thread, not the other way round) -- for example again via a custom event or via a shared resource.

Alternatively you can spin the thread inside a (semi-)busy loop until the answer arrives through an event.

vfernandez
5th February 2006, 16:40
Sorry, I forgot to say I'm using QT4. So I could use events but I think using signal/slots across threads is a better approach and you know with QT4 it's now possible. Basically it would be a similar mechanism (send the signal, block and wait until the GUI thread wakes up the worker thread), and I could pass the wait condition as a parameter in the signal. Anyway I don't like much that way of doing it. If there's no better way... Thanks anyway.

wysota
5th February 2006, 18:24
Sorry, I forgot to say I'm using QT4.
I know that because you said the thread went on during slot execution.


So I could use events but I think using signal/slots across threads is a better approach and you know with QT4 it's now possible. The truth is crossthread signals are implemented as events, so you'd be using events anyway.


Basically it would be a similar mechanism (send the signal, block and wait until the GUI thread wakes up the worker thread), and I could pass the wait condition as a parameter in the signal.
Hmm... what happens if two slots are connected to the same signal? You get an undefined behaviour with the wait condition. With custom event you can be sure it gets fired once and you can pass whatever you want in the event data anyway.


Anyway I don't like much that way of doing it. If there's no better way... Thanks anyway.
Yes, there is. Don't spawn a new thread until the user acknowledges the key. Or emit the signal (or send event, whatever), save the data and return the flow (for example end the thread or make it do something else). After the dialog is closed, send a signal, which will spawn a new thread and continue execution or just inform it of the result. If the user rejects the key, you don't need that thread anyway, so you can kill it.

Please also note that you are trying to use a non-event driven library in a event-driven environment, so you have to be prepared to face problems.