6

从阅读这个博客、这个博客和其他一些博客来看,子类化 QThread 是不好的做法。所以我尝试应用这种方法。

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

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

这里是 CommsHandlerIP 类,方法不包括在内。

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

问题是即使您移动 CommsHandlerIP,QTimer 和 QTcpSocket(在 CommsHandlerIP 类中)也在主线程中。所以我无法启动计时器或连接套接字。

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

我该怎么办?

4

3 回答 3

6

类实例在调用线程上创建。 QTimer继承QObject. Qt如果调用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();

当线程启动时,调用CommsHanderIP Initialise函数;这是您应该在调用之前创建和设置QTcpSocketand对象的地方。由于在创建这些对象之前在新线程中运行,它们还将共享相同的线程亲和性。QTimerRun()CommsHandlerIP

于 2013-10-08T16:12:16.970 回答
2

有一种更简单的方法可以实现所有这些,它遵循相同的算法,但不涉及使用QRunnableQThreadPool创建线程和更改线程关联所需的所有样板

如果我转换 Merlin069 的示例,您将看到它是如何简化代码的:

class CommsHandlerIP : public QObject, public QRunnable
{
    Q_OBJECT
    public:
       void run();

    public slots:
        //... any slots

    signals:
        //... any signals

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

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

     //...

     delete m_pTimer;
     delete m_pSocket;
}

QThreadPool::globalInstance()->start(new CommsHandlerIP);
于 2013-10-09T13:19:58.963 回答
2

在搜索 Timer 行为和 movetoThread 时,我偶然发现了这一点。公认的答案是一个很好的解决方法,但并不是问题的根本原因。有一个一般规则,当您移动一个对象时,所有子对象也会移动。所以你只需要确保 QTimer 成为一个孩子,所以在它的构造函数中传递 this 指针。

CommsHandlerIPL::CommsHandlerIP()
: QObject(), m_pTimer(new QTimer(this))        // <=== crucial to make it a "child" object 
{
}
于 2019-03-19T05:23:20.250 回答