QThread, QTimer, and TCP messaging
-
Qt 4.8, Windows XP:
I have a thread that manages my TCP messages and opens / maintains / closes the socket at the appropriate times.
This same thread starts a QTimer, 200 ms, defined in my thread's data, that pumps an event in my thread's class once (if) the socket is open. So the timer and its event belong to the thread, as best I understand the idea.
The QTimer timeout event sends a TCP message through the port belonging to the thread, it's a keep-alive message for this particular hardware item. Has to be sent regularly or the device "goes away" which won't do.
When the message is sent, I get this error:
"QSocketNotifier: socket notifiers cannot be enabled from another thread"
As far as I can tell, I am sending the message from the same thread and would expect any signals, etc., to be owned / handled etc. by it.
Can anyone tell me what I'm missing here?
PS: The message is sent, the device does stay alive... it's just that I'm getting this runtime error on the Qt error console and I've very concerned that there are internal problems lurking because of it.
The message does NOT occur running under OS X 10.6. I don't know why.
-
Note that, slots of QThread doesn't belong to the thread managed by QThread. Instead, they belong to the thread where the QThread created.
-
You mean, the event the timer is calling belongs to the thread's parent, even though the timer -- and the event it calls -- belong to the thread?
So...
How would I create a keepalive? Launch a thread from the thread, which.... has a timer... which belongs to the parent... which is the the actual thread with the socket?
Seems... unreasonable
-
ok, no. You can't put a QTimer in a thread that is a subthread, because you can't use Q_OBJECT, and without Q_OBJECT, the signals and slots mechanism doesn't work.
-
ok, got it
The low level timer, QObject::starttimer(etc.), runs IN the thread. So I can use that, and no signal, slot of anything, just have to reimplment QObject::timerevent() and that works just fine.
-
The central question is which thread the timer object belongs to. If it is created in the constructor, it belongs to the thread that created the thread object. If it is created in the run method, it belongs to the new thread.
I think we do not know enough about your code to give you a better answer, though.
-
Problem is solved now, but I appreciate the insight of timer ownership. I'm sure that will come in useful. :)