简体   繁体   English

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

[英]Is this the correct way to use a QThread?

I am looking at some github projects, where one of them did the UDPlink in the following way, first it subclass QThread to create a class UDPLink:public QThread and its constructor and deconstructor is like: 我正在看一些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();
}

Though the code did compile and work, but I wonder whether this way of using a QThread would be correct? 虽然代码确实可以编译和工作,但是我想知道这种使用QThread的方式是否正确?

The Qt docs for QThread describe the two ways threading can be done with QThread. QThread的Qt文档描述了可以使用QThread完成线程的两种方式。 Sub-classing QThread was the only way to use QThread initially. 子类化QThread是最初使用QThread的唯一方法。 To use QThread in this manner, override the run method, which is the QThread method that runs on a new thread. 要以这种方式使用QThread,请重写run方法,该方法是在新线程上运行的QThread方法。 QThread should be thought of as a thread manager, not an object that runs on a separate thread itself. 应该将QThread视为线程管理器,而不是在单独线程上运行的对象。 From the docs: 从文档:

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(). 重要的是要记住,一个QThread实例存在于实例化它的旧线程中,而不是存在于调用run()的新线程中。 This means that all of QThread's queued slots will execute in the old thread. 这意味着所有QThread排队的插槽都将在旧线程中执行。 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. 新插槽不应直接实现到子类QThread中。

When subclassing QThread, keep in mind that the constructor executes in the old thread while run() executes in the new thread. 子类化QThread时,请记住,构造函数在旧线程中执行,而run()在新线程中执行。 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文档页面

It's because QThread is a thread manager class that a solution for moving objects to threads was created. 因为QThread是线程管理器类,所以创建了将对象移动到线程的解决方案。 The comment in the code you provided makes a statement about this change, since that article states that moveToThread(this) isn't a good practice. 您提供的代码中的注释说明了此更改,因为该文章指出moveToThread(this)不是一个好习惯。

Creating an object and moving it to a thread and sub-classing QThread are both valid approaches to threading with Qt, as the documentation now states clearly. 正如文档中清楚指出的那样,创建对象并将其移动到线程中以及对QThread进行子类化都是使用Qt进行线程化的有效方法。 There is a benefit to using the worker-object approach, if you desire to use signal/slot connections across thread boundaries: a worker object will have its slots available on the thread it is moved to. 如果希望跨线程边界使用信号/插槽连接,则使用工作对象方法会有好处:工作对象将在其移动到的线程上具有可用的插槽。

As Qt developer recommended, Code you mentioned is not correct way to use QThread. 正如Qt开发人员推荐的那样,您提到的代码不是使用QThread的正确方法。

Recommended way is suggested here . 建议的方法在这里建议。

Sample code from Post. 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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM