使用QThread和QTcpSocket正确使用QThread和moveToThread

dye*_*yes 4 c++ qt multithreading qthread

从阅读这篇博客,这个博客和其他一些人,Subclassing QThread是不好的做法.所以我尝试应用这种方法.

但我的问题是我在类中有一个QTimer和一个QTcpSocket我想转移到另一个线程.突然间,它并不像使用的例子那么容易.:(

QThread m_commsThread;
m_pICommsHandler = new CommsHandlerIP();
m_pICommsHandler->moveToThread(&m_commsThread);
m_commsThread.start();
Run Code Online (Sandbox Code Playgroud)

这里是CommsHandlerIP类,不包括方法.

class CommsHandlerIP : public QObject
{
    Q_OBJECT
public:
    CommsHandlerIP();
    ~CommsHandlerIP(void);
protected:
    QTcpSocket m_TCPSocket;
    QTimer m_timer;
}
Run Code Online (Sandbox Code Playgroud)

问题是即使你移动CommsHandlerIP,QTimer和QTcpSocket(在CommsHandlerIP类内)也在主线程中.所以我无法启动计时器或连接插座.

如果我尝试moveToThread QTimer和QTcpSocket(在构造函数中通过传递线程指针),当我离开应用程序时,这变得非常混乱.

我该怎么办?

The*_*ght 5

类实例在调用线程上创建. QTimer继承QObject.Qt如果调用,则每个Thread on 都可以有一个事件循环exec().所以你想转移QTimer到另一个线程的事件循环.所以你应该手动移动它.

因此,延迟创建直到移动对象后: -

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();
Run Code Online (Sandbox Code Playgroud)

线程启动时,调用CommsHanderIP Initialise函数; 这是你应该在调用之前创建和设置QTcpSocketQTimer对象的地方Run().由于CommsHandlerIP在创建这些对象之前在新线程中运行,它们也将共享相同的线程关联.

  • 在构造函数中创建它们时,将`this`作为父项传递给`m_TCPSocket`和`m_timer`就足够了.这是因为[QObject :: moveToThread()](http://qt-project.org/doc/qt-5.0/qtcore/qobject.html#moveToThread)`更改​​了此对象及其子对象的线程关联.所以你不必拖延他们的创作. (3认同)
  • @ Merlin069 AFAIK,如果类型是`Qt :: AutoConnection`,那么在调用`moveToThread()`之前建立连接并不重要.这是因为`如果信号是从与接收对象不同的线程发出的,则信号排队,表现为Qt :: QueuedConnection.否则,直接调用插槽,表现为Qt :: DirectConnection.发射信号时确定连接类型. (3认同)