Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
698 views
in Technique[技术] by (71.8m points)

c++ - Using QThread and moveToThread properly with QTimer and QTcpSocket

From reading this blog, this blog and some others, Subclassing QThread is bad practice. So I tried to apply this method.

But my problem is that I have a QTimer and a QTcpSocket in the class I want to move to a different thread. Suddenly, it's not as easy as it the examples used. :(

QThread m_commsThread;
m_pICommsHandler = new CommsHandlerIP();
m_pICommsHandler->moveToThread(&m_commsThread);
m_commsThread.start();

And here is the CommsHandlerIP class, methods are not included.

class CommsHandlerIP : public QObject
{
    Q_OBJECT
public:
    CommsHandlerIP();
    ~CommsHandlerIP(void);
protected:
    QTcpSocket m_TCPSocket;
    QTimer m_timer;
}

Issue is that the QTimer and the QTcpSocket (inside CommsHandlerIP class) are in the main thread even if you move CommsHandlerIP. So I can't start the timer or connect the socket.

If I try to moveToThread the QTimer and QTcpSocket (inside the constructor by passing the thread pointer for instance), this become really messy when I leave the app.

What should I do?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Class Instances are created on the calling thread. QTimer inherits QObject. Each Thread on Qt can have an event loop if it calls exec(). so you want to move QTimer to an event loop on another thread. so you should manually move it.

Therefore, delay their creation until after you move the object: -

class CommsHandlerIP : public QObject
{
    Q_OBJECT

    public slots:
       void Initialise();

    private: 
       void Run();

       // c++ 11, initialising in headers...
       QTimer* m_pTimer = NULL;
       QTcpSocket* m_pSocket = NULL;   
};

void CommsHandlerIP::Initialise()
{
     m_pTimer = new QTimer(this);
     m_pSocket = new QTcpSocket(this);

     Run();
}

QThread m_commsThread;
m_pICommsHandler = new CommsHandlerIP();

// Note Qt 5 connect style
connect(&m_commsThread, &QThread::started, m_pICommsHandler, &CommsHandlerIP::Initialise);
m_pICommsHandler->moveToThread(&m_commsThread);
m_commsThread.start();

When the thread is started, the CommsHanderIP Initialise function is called; this is where you should create and setup the QTcpSocket and QTimer objects before calling Run(). As the CommsHandlerIP is running in the new thread before creating those objects, they will also share the same thread affinity.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...