你这样做是错误的
我知道这样说很大胆,或许有点挑衅,但在同时,我不禁认为(假想的)下面的类是一个不正确使用Qt的程序。
class MyThread : public QThread
{
public:
MyThread()
{
moveToThread(this);
}
void run();
signals:
void progress(int);
void dataReady(QByteArray);
public slots:
void doWork();
void timeoutHandler();
};
我觉得moveToThread(this)悄悄进入人们的代码,是因为他们在博客里有人用它。打开快速的网络搜索,打开了几个博客,他们都遵循下面的模式:
1、子类化QThread
2、添加signals和slots
3、测试,发现slots不是从正确的线程里调用
4、google一下,搜:moveToThread(this),有评论说添加这个后似乎可以工作
在我看来,这些问题从步奏1开始。QThread的设计的目的是作为一个操作系统线程的接口或者控制点,而不是用来堆放想要在一个thread实现的代码。在面向对象编程中,我们子类化,是因为我们想要扩展或者专用基类的功能。我能想到子类化QThread唯一有效的原因是增加QThread不具有的功能。比如提供一个指向内存的指针作为线程的堆栈
,或者增加实时接口/支持。对于下载文件、查询数据库或者其他不应该添加到QThread子类里的程序,都应该在自己的子类里封装。
通常这意味着,你要实现的类要继承自QObject而不是QThread。当你需要执行一些初始化工作时,QThread有一个started()信号可以供你connect。当你需要在新的线程里实现你的代码时,你可以实例化QThread,用moveToThread()函数把对象分配到该线程。即使你还在用moveToThread()告诉QT来执行你子类化QThread里的代码,我们也要保持线程接口的独立(这一句很难理解啊,是说子类化QThread不能有父对象吗?by hustyangju 2013 - 07-26)。如果有必要,你可以给一个类的不同实例分配一个单一的线程,或者不同类的实例分配一个单一的线程。换句话说,把一个单一的实例绑定到一个线程是不必要的。
很多人对带线程的QT编程很困惑。早期版本的QThread是很抽象的,所以子类化是必要的。到了Qt4.4, QThread::run()默认实现了,不必再子类化了。在线程里不同对象可以通过信号和槽链接,因此在线程编程里有一种比较便捷的方法。