My mistake here, event loop isn't required. But I'm not sure if you are aware that in such case your sendMessage slot isn't executed in client thread. There are three threads here: main thread, client thread and sender thread. Socket reading is done in client thread, that's obvious. But sendMessage slot is executed either in main thread (if you make queued connection between Sender and Client) or in sender thread (if you make direct connection between Sender and Client).
I wrote a program like yours (two threads, Client and Sender) and I don't have that problem. Of course "QObject: Cannot create children for a parent that is in a different thread." is still there, but I wasn't able to reproduce "QSocketNotifier: socket notifiers cannot be disabled from another thread"
Last edited by danadam; 19th March 2007 at 21:38.
The Wheel weaves as the Wheel wills.
On the contrary, it is required to make the queued connections work.
Most likely it's executed in the Sender thread. QThread objects live in the thread that has created them, so most likely both Sender and Client objects live in the main thread, while the socket lives in the Client thread.
Since both Sender and Client live in the same thread, most likely a direct connection was made between them, whereas it should be a queued connection. When making connections between thread object, it's safer to explicitly specify the connection type.
To make things clear, here is output from my test program (three threads: main, client, sender, neither client nor sender has event loop, client and sender live in main thread, socket lives in client thread):
Qt::AutoConnection (slot is executed in main thread):
Qt Code:
"main, thread: b70a28e0" server is listening incoming connection "client started, thread: b6e82bb0" "sender started, thread: b6681bb0" "sender emit signal, thread: b6681bb0" "client slot, thread: b70a28e0" "sender emit signal, thread: b6681bb0" "client slot, thread: b70a28e0"To copy to clipboard, switch view to plain text mode
Qt::DirectConnection (slot is executed in sender thread):
Qt Code:
"main, thread: b71698e0" server is listening incoming connection "client started, thread: b6f49bb0" "sender started, thread: b6748bb0" "sender emit signal, thread: b6748bb0" "client slot, thread: b6748bb0" "sender emit signal, thread: b6748bb0" "client slot, thread: b6748bb0"To copy to clipboard, switch view to plain text mode
Qt::QueuedConnection (slot is executed in main thread):
Qt Code:
"main, thread: b70df8e0" server is listening incoming connection "client started, thread: b6ebfbb0" "sender started, thread: b66bebb0" "sender emit signal, thread: b66bebb0" "client slot, thread: b70df8e0" "sender emit signal, thread: b66bebb0" "client slot, thread: b70df8e0"To copy to clipboard, switch view to plain text mode
The Wheel weaves as the Wheel wills.
That's quite interesting. The docs say:So it looks like that if you use Qt::AutoConnection, the effective connection type is established for each signal, not once when the connection is created.If the signal is emitted from the thread in which the receiving object lives, the slot is invoked directly, as with Qt::DirectConnection; otherwise the signal is queued, as with Qt::QueuedConnection.
It looks like the Client object lives in the main thread, so the meta call events go through main thread's event queue. One possible solution is to use QObject::moveToThread() (of course in such case there must be an event loop running in the Client thread).
I solve the problem as below, but there is other things to solve.
Sender thread lives in main thread.
Client lives main thread.
Socket lives in Client thread.
As you have said , with direct connection between sender and client ,Client slot is invoked in sender thread. That is why, slot can not write to socket due to fact that socket lives in Client thread.
With queued connection between sender and client , slot of Client is invoked in main thread because client lives in main thread. That is why, client slot can not write socket due to fact that socket lives in Client thread not in main thread.
To solve the problem, I have created new class that is responsible for initialization of the socket. This class also have slot that writes to the socket. I have created this class in the run block of the Client class. And connect to signal of the sender with slot of this class. it worked correctly using queud connection but as you said I needed "exec" call to be able use queued connection.
But when I call "exec" it blocks in the run block. I can not do anything inside. for example I can not use blocking approach as follows.
Qt Code:
while (!quit) { if (tcpSocket->waitForReadyRead(Timeout)) { // Read data in >> buffer; qDebug() << buffer<<endl; } }To copy to clipboard, switch view to plain text mode
because I have to read and write same socket in my design I have to alternative
1 -) Do not use blocking approach. Use simply signal / slot way. but as I know signals are slow . my application time critical. should handle lots of messages.I can not choose this approach.
2-) use blocking approach but create separe sockets for writing and reading.
3-) Use an other socket library
am I right ?
To say the truth I don't know why you can't write to socket in different thread. My previous guessing was only... er... guessing. I checked that and it appears that there is no problem with writing to socket in sender thread or main thread. Client slot in the above examples did it and it wasn't complaining.
The Wheel weaves as the Wheel wills.
Bookmarks