0
votes

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.

2
Since the timer is network related it should be on the network thread. Make sure the slot connected to it is in an object also on the network thread.Kevin Krammer
The timer probably still lives in the main thread. First: Create the socket directly on the thread or set the socketdescriptor and open the socket using a QueuedConnection. Do not create the timer in the constructor and call movetothread on the object, instead call a initialize function using invokeMethod or a queued signal/slot connection. In this function create the timer using new. Otherwise the timer will actually stay in the main threadSebastian Lange
Hi guys! Thanks for the quick replies. Kevin, I had the timer completely moved in the network thread, with it's corresponding slot on the network thread. Btw, the timer was created on the heap.ionutCb

2 Answers

1
votes

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.

0
votes

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;
}