Reputation: 13
Brief of environment: I have a device on which runs an application written in qt. It has a main thread which handles Database operations (SQlite) and a separate thread for networking operations (via 3G). Mains thread Event loop is ran by QCoreApplication::exec and the other thread which handles networking operations is ran by QThread::exec. Btw, socket thread affinity is changed after it's started (Eg. moveToThread(socketThreadPtr))
Brief of problem: Main thread is busy in a loop, in order to select around 10k records from database and that loop takes about +30 seconds. In the network thread there is a 15 seconds timer which has to send a keep alive message each time expires. The problem is that the slot for timeout() signal is executed only after the loop is finished.
Solution founded until now(but not satisfying): If I call QCoreApplication::processEvents in the loop that selects the records, problem is solved, but I wonder if a solution exists instead of this workaround.
Remark: The timer, signal and slot, which gives the command to send the keep alive message is currently handled in the main thread( but the read/write happens in the network thread). Also, I moved the timer on the network thread but I got the same result as being on the main thread.
Upvotes: 1
Views: 413
Reputation: 1763
You have to create timer in your network thread, maybe Qtimer is a member of network thread, so the network thread will be constructed in main thread and thread affinity of its children's set to main thread, next you have moved network thread to new Qthread, but what about Qtimer? it still lives in main thread (except when you explicitly define network class as it's parent, so as you said moveToThread will affect object's children as well as Qtimer)
The Qtimer should be constructed in network thread, you can construct a new Qtimer in one of the network thread slots and connecting it to the Qthread::start signal. So by calling start method of Qthrad your slot will be executed on new thread and Qtimer will be constructed on that thread respectively.
Upvotes: 1
Reputation: 4029
Something like this should actually create the socket and the timer in your dedicated thread, given your main-thread is the server and clients should be handled in threads. Otherwise just use QTcpSocket::connectToHost()
or QTcpServer:::bind()
in your initialize function.
Mainthread:
auto t = new QThread();
t->start();
auto o = new MyThreadObject();
o.moveToThread(t);
o.setDescriptor(socketDesc);
QMetaObject::invokeMethod(o, "initialize", Qt::QueuedConnection);
MyThreadObject:
class MyThreadObject : public QObject
{
Q_OBJECT
public:
MyThreadObject(){...};
void setDescriptor(qintptr socketdescriptor)
{
m_desc = socketdescriptor;
}
public slots:
void initialize()
{
m_tcpSocket = new QTcpSocket();
m_tcpSocket->setSocketDescriptor(m_desc);
//socket configuration
m_timer = new QTimer();
//timer configuration
m_timer->start();
}
private:
QTcpSocket* m_tcpSocket;
QTimer* m_timer;
qintptr m_desc;
}
Upvotes: 0