什么是正确的方式实现QThread ...(示例请...) [英] what is the correct way to implement a QThread... (example please...)

查看:248
本文介绍了什么是正确的方式实现QThread ...(示例请...)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

QThread的Qt文档说,要从QThread创建一个类,并实现run方法。



下面是从4.7 Qthread文档中获取...


创建你自己的线程,子类QThread和reimplement run()。例如:




  class MyThread:public QThread 
{
public :
void run();
};

void MyThread :: run()
{
QTcpSocket socket;
//连接QTcpSocket的信号有意义的
...
socket.connectToHost(hostName,portNumber);
exec();
}

所以在我创建的每个线程中,我已经做到了对于大多数事情,它的工作原理很好(我不会在任何我的对象中实现moveToThread(this),它的工作原理很好)。



我上周打了个陷阱设法通过在我创建我的对象的地方找到它),并发现以下博文。这里基本上说,子类化QThread真的不是正确的方法(文档不正确)。



这是来自一个Qt开发人员,所以在乍一看我有兴趣,进一步思考,同意他的看法。遵循OO原则,您只希望子类进一步增强该类...不要直接使用类方法...这就是为什么实例化...



假设我想将一个自定义的QObject类移动到一个线程上,这将是正确的方法?在这篇博文中,他说他有一个例子,但如果有人可以进一步向我解释,那将非常感激!



更新:



由于这个问题得到如此多的关注,这里是4.8文档的复制和粘贴,以正确的方式来实现QThread 。

  class Worker:public QObject 
{
Q_OBJECT
QThread workerThread;

public slots:
void doWork(const QString& parameter){
// ...
emit resultReady(result);
}

信号:
void resultReady(const QString& result);
};

class Controller:public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller(){
Worker * worker = new Worker;
worker-> moveToThread(& workerThread);
connect(workerThread,SIGNAL(finished()),worker,SLOT(deleteLater()));
connect(this,SIGNAL(operate(QString)),worker,SLOT(doWork(QString)));
connect(worker,SIGNAL(resultReady(QString)),这个,SLOT(handleResults(QString)));
workerThread.start();
}
〜Controller(){
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString&);
信号:
void operate(const QString&);
};

我仍然认为值得指出的是,它们包含一个额外的 Worker :: workerThread 成员是不必要的,在他们的例子中从未使用过。删除那块,这是Qt中如何做线程的一个正确例子。

解决方案

关于我唯一可以想到的要添加的是进一步声明, QObject 与单个线程具有亲和力。这通常是创建 QObject 的线程。因此,如果您在应用程序主线程中创建了一个 QObject ,并希望在另一个线程中使用它,则需要使用 moveToThread()来改变亲和力。



这个节省了 QThread 的子类,并在 run()方法,从而保持你的东西很好地封装。



该博客文章包含一个示例。它很短,但它显示了基本的想法。创建您的 QObject s,连接您的信号,创建您的 QThread ,移动您的 QObjects QThread 并启动线程。信号/时隙机制将确保线程边界正确和安全地交叉。



如果您必须在该机制外的对象上调用方法,则可能需要引入同步。



我知道Qt除了线程之外还有一些其他不错的线程设施可能值得熟悉,但我还没有这样做:)


The Qt documentation for QThread says to create a class from QThread, and to implement the run method.

Below is taken from the 4.7 Qthread documentation...

To create your own threads, subclass QThread and reimplement run(). For example:

 class MyThread : public QThread
 {
 public:
     void run();
 };

 void MyThread::run()
 {
     QTcpSocket socket;
     // connect QTcpSocket's signals somewhere meaningful
     ...
     socket.connectToHost(hostName, portNumber);
     exec();
 }

So in every single thread I've created, I've done just that and for most things it works just fine (I do not implement moveToThread(this) in any of my objects and it works great).

I hit a snag last week (managed to get through it by working around where I created my objects) and found the following blog post. Here is basically says that subclassing QThread really isn't the correct way to do it (and that the documentation is incorrect).

This is coming from a Qt developer so at first glance I was interested and upon further reflection, agree with him. Following OO principles, you really only want to subclass a class to further enhance that class... not to just use the classes methods directly... thats why you instantiate...

Lets say I wanted to move a custom QObject class to a thread... what would be the 'correct' way of doing it? In that blog post, he 'says' he has an example somewhere... but if someone could further explain it to me it'd be greatly appreciated!

Update:

Since this question gets so much attention, here is a copy and paste of the 4.8 documentation with the 'proper' way to implement a QThread.

class Worker : public QObject
 {
     Q_OBJECT
     QThread workerThread;

 public slots:
     void doWork(const QString &parameter) {
         // ...
         emit resultReady(result);
     }

 signals:
     void resultReady(const QString &result);
 };

 class Controller : public QObject
 {
     Q_OBJECT
     QThread workerThread;
 public:
     Controller() {
         Worker *worker = new Worker;
         worker->moveToThread(&workerThread);
         connect(workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
         connect(this, SIGNAL(operate(QString)), worker, SLOT(doWork(QString)));
         connect(worker, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
         workerThread.start();
     }
     ~Controller() {
         workerThread.quit();
         workerThread.wait();
     }
 public slots:
     void handleResults(const QString &);
 signals:
     void operate(const QString &);
 };

I still believe that it is worthwhile to point out that they include an extra Worker::workerThread member that is unnecessary and is never used in their example. Remove that piece and it is a proper example of how to do threading in Qt.

解决方案

About the only thing I can think of to add is to further state that QObjects have an affinity with a single thread. This is usually the thread that creates the QObject. So if you create a QObject in the app's main thread and want to use it in another thread, you need to use moveToThread() to change the affinity.

This saves having to subclass QThread and creating your objects in the run() method, thus keeping your stuff nicely encapsulated.

That blog post does include a link to an example. It is pretty short but it shows the basic idea. Create your QObjects, connect your signals, create your QThread, move your QObjects to the QThread and start the thread. The signal/slot mechanisms will ensure that thread boundaries are crossed properly and safely.

You may have to introduce synchronization if you have to call methods on your object outside of that mechanism.

I know Qt has some other nice threading facilities beyond threads that are probably worth getting familiar with but I have yet to do so :)

这篇关于什么是正确的方式实现QThread ...(示例请...)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆