这是使用 QThread 的正确方法吗?
Posted
技术标签:
【中文标题】这是使用 QThread 的正确方法吗?【英文标题】:Is this the correct way to use a QThread? 【发布时间】:2015-03-13 02:14:15 【问题描述】:我正在查看一些 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 的方式是否正确?
【问题讨论】:
【参考方案1】:QThread 的 Qt 文档描述了使用 QThread 完成线程的两种方式。子类化 QThread 是最初使用 QThread 的唯一方法。要以这种方式使用 QThread,请重写 run 方法,这是在新线程上运行的 QThread 方法。 QThread 应该被认为是一个线程管理器,而不是一个运行在单独线程本身上的对象。来自文档:
重要的是要记住 QThread 实例存在于旧的 实例化它的线程,而不是在调用 run() 的新线程中。 这意味着 QThread 的所有排队槽都将在旧的 线。因此,希望在新线程中调用槽的开发人员 必须使用工作对象方法;新插槽不应该 直接在子类 QThread 中实现。
子类化 QThread 时,请记住构造函数执行 在旧线程中,而 run() 在新线程中执行。如果是会员 从这两个函数访问变量,然后变量是 从两个不同的线程访问。检查这样做是否安全。
QThread documentation page
因为 QThread 是一个线程管理器类,所以创建了将对象移动到线程的解决方案。您提供的代码中的注释说明了此更改,因为该文章指出 moveToThread(this) 不是一个好习惯。
创建一个对象并将其移动到一个线程和子类化 QThread 都是使用 Qt 进行线程化的有效方法,正如文档现在明确指出的那样。如果您希望跨线程边界使用信号/槽连接,则使用工作对象方法有一个好处:工作对象将在其移动到的线程上拥有可用的槽。
【讨论】:
【参考方案2】:正如 Qt 开发人员所建议的那样,您提到的代码不是使用 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();
【讨论】:
以上是关于这是使用 QThread 的正确方法吗?的主要内容,如果未能解决你的问题,请参考以下文章
重点:怎样正确的使用QThread类(注:包括推荐使用QThread线程的新方法QObject::moveToThread)