我正在看一些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的方式是否正确?
答案 0 :(得分:3)
QThread的Qt文档描述了使用QThread完成线程化的两种方法。子类化QThread是最初使用QThread的唯一方法。要以这种方式使用QThread,请覆盖run方法,该方法是在新线程上运行的QThread方法。 QThread应该被认为是一个线程管理器,而不是一个在单独的线程上运行的对象。来自文档:
重要的是要记住QThread实例存在于旧版本中 实例化它的线程,而不是在调用run()的新线程中。 这意味着所有QThread排队的插槽都将在旧版本中执行 线。因此,希望在新线程中调用插槽的开发人员 必须使用工人对象方法;新的插槽不应该 直接实现到子类QThread。
在继承QThread时,请记住构造函数的执行 在旧线程中,run()在新线程中执行。如果是会员 从两个函数访问变量,然后变量是 从两个不同的线程访问。检查这样做是否安全。
因为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();