这是使用QThread的正确方法吗?

时间:2015-03-13 02:14:15

标签: c++ qt qthread

我正在看一些github项目,其中一个以下列方式完成了UDPlink, 首先它将QThread子类化为创建一个类UDPLink:public QThread 它的构造函数和解构函数就像:

UDPLink::UDPLink(UDPConfiguration* config)
    : _socket(NULL)
    , _connectState(false)
{
    Q_ASSERT(config != NULL);
    _config = config;
    _config->setLink(this);

    // We're doing it wrong - because the Qt folks got the API wrong:
    // http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/
    moveToThread(this);

    // Set unique ID and add link to the list of links
    _id = getNextLinkId();
    qDebug() << "UDP Created " << _config->name();
}

UDPLink::~UDPLink()
{
    // Disconnect link from configuration
    _config->setLink(NULL);
    _disconnect();
    // Tell the thread to exit
    quit();
    // Wait for it to exit
    wait();
    this->deleteLater();
}

虽然代码确实编译和工作,但我想知道这种使用QThread的方式是否正确?

2 个答案:

答案 0 :(得分:3)

QThread的Qt文档描述了使用QThread完成线程化的两种方法。子类化QThread是最初使用QThread的唯一方法。要以这种方式使用QThread,请覆盖run方法,该方法是在新线程上运行的QThread方法。 QThread应该被认为是一个线程管理器,而不是一个在单独的线程上运行的对象。来自文档:

  

重要的是要记住QThread实例存在于旧版本中   实例化它的线程,而不是在调用run()的新线程中。   这意味着所有QThread排队的插槽都将在旧版本中执行   线。因此,希望在新线程中调用插槽的开发人员   必须使用工人对象方法;新的插槽不应该   直接实现到子类QThread。

     

在继承QThread时,请记住构造函数的执行   在旧线程中,run()在新线程中执行。如果是会员   从两个函数访问变量,然后变量是   从两个不同的线程访问。检查这样做是否安全。

QThread documentation page

因为QThread是一个线程管理器类,所以创建了一个将对象移动到线程的解决方案。您提供的代码中的注释会对此更改做出声明,因为该文章指出moveToThread(this)不是一个好习惯。

创建一个对象并将其移动到一个线程和子类QThread都是使用Qt进行线程化的有效方法,正如文档现在清楚地说明的那样。如果您希望跨线程边界使用信号/插槽连接,则使用工作对象方法有一个好处:工作对象将在其移动到的线程上使用其插槽。

答案 1 :(得分:1)

正如Qt开发人员所推荐的那样,你提到的Code是使用QThread的正确方法。

建议使用推荐方法here

Post的示例代码。

Producer producer;
Consumer consumer;
producer.connect(&consumer, SIGNAL(consumed()), SLOT(produce()));
consumer.connect(&producer, SIGNAL(produced(QByteArray *)), SLOT(consume(QByteArray *)));

// they both get their own thread
QThread producerThread;
producer.moveToThread(&producerThread);
QThread consumerThread;
consumer.moveToThread(&consumerThread);

// go!
producerThread.start();
consumerThread.start();