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

Is this the correct way to use a QThread?

我正在查看一些 github 项目,其中一个项目通过以下方式实现了 UDPlink, 首先它subclass QThread创建一个class 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 的方式是否正确?

根据 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 的 Qt 文档描述了使用 QThread 完成线程化的两种方式。 Sub-classing QThread 是最初使用 QThread 的唯一方法。要以这种方式使用 QThread,请覆盖 运行 方法,这是 运行 在新线程上的 QThread 方法。 QThread 应该被认为是一个线程管理器,而不是 运行 在单独线程本身上的对象。来自文档:

It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run(). This means that all of QThread's queued slots will execute in the old thread. Thus, a developer who wishes to invoke slots in the new thread must use the worker-object approach; new slots should not be implemented directly into a subclassed QThread.

When subclassing QThread, keep in mind that the constructor executes in the old thread while run() executes in the new thread. If a member variable is accessed from both functions, then the variable is accessed from two different threads. Check that it is safe to do so.

QThread documentation page

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

创建对象并将其移动到线程和子classing QThread 都是使用 Qt 进行线程处理的有效方法,正如文档现在明确指出的那样。如果您希望跨线程边界使用 signal/slot 连接,则使用工作对象方法有一个好处:工作对象将在它移动到的线程上有可用的插槽。