看了不少Qt线程的东西,下面总结一下Qt新建一个线程的方法。

一、继承QThread

继承QThread,这应该是最常用的方法了。我们可以通过重写虚函数void QThread::run ()实现我们自己想做的操作,实现新建线程的目的。前面已经介绍了Qthread,这里就不重复了。

这种方法,我们每一次要新建一个线程都需要继承Qthread,实现一个新的类,有点不太方便。但是相对于Qrunnable,这种方法的好处就是我们可以直接调用对象的start()函数启动线程,而Qrunnable必须借助QthreadPool。

二、继承QRunnable

Qrunnable是所有可执行对象的基类。我们可以继承Qrunnable,并重写虚函数void QRunnable::run () 。我们可以用QThreadPool让我们的一个QRunnable对象在另外的线程中运行,如果autoDelete()返回true(默认),那么QThreadPool将会在run()运行结束后自动删除Qrunnable对象。可以调用void QRunnable::setAutoDelete ( bool autoDelete )更改auto-deletion标记。需要注意的是,必须在调用QThreadPool::start()之前设置,在调用QThreadPool::start()之后设置的结果是未定义的。

下面是我写的简单的例子:

class Runnable:publicQRunnable

{

//Q_OBJECT   注意了,Qrunnable不是QObject的子类。

public:

Runnable();

~Runnable();

voidrun();

protected:

private:

};

Runnable::Runnable():QRunnable()

{

}

Runnable::~Runnable()

{

cout<<"~Runnable()"<<endl;

}

void Runnable::run()

{

cout<<"Runnable::run()thread :"<<QThread::currentThreadId()<<endl;

cout<<"dosomething ...."<<endl;

}

int main(int argc, char *argv[])

{

QCoreApplication a(argc, argv);

cout<<"mainthread :"<<QThread::currentThreadId()<<endl;

Runnable runObj;

QThreadPool::globalInstance()->start(&runObj);

returna.exec();

}

由结果可看出,run()确实是在不同于主线程的另外线程中运行的,而且在运行结束后就调用了析构函数,因为默认是可以自动被销毁的。

我们可以对同一个对象多次调用QThreadPool::start(),如果是可以自动被销毁的,Qrunnable对象会在最后一个线程离开了run函数之后才被销毁的。

int main(int argc, char *argv[])

{

QCoreApplication a(argc, argv);

cout<<"mainthread :"<<QThread::currentThreadId()<<endl;

Runnable runObj;

QThreadPool::globalInstance()->start(&runObj);

QThreadPool::globalInstance()->start(&runObj);

QThreadPool::globalInstance()->start(&runObj);

returna.exec();

}

我三次调用QThreadPool::globalInstance()->start(&runObj);,但是在三次都执行完之后才运行析构函数。

这种新建线程的方法的最大的缺点就是:不能使用Qt的信号—槽机制,因为Qrunnable不是继承自QObject。所以我们要想知道线程是否运行结束或获取运行结果可能会比较麻烦。还有就是我们不能直接调用run()启动线程,必须借助于QthreadPool。

但是这种方法的好处就是,可以让QThreadPool来管理线程,QThreadPool会自动的清理我们新建的Qrunnable对象。

三、使用moveToThread

首先我们必须实现继承QObject的一个类,实现我们想要的功能。

class Worker:publicQObject

{

Q_OBJECT

public:

Worker();

~Worker();

protected slots:

voidfun1();

void fun2();

private:

};

Worker::Worker():QObject()

{        }

Worker::~Worker()

{     }

void Worker::fun1()

{

cout<<"Worker::fun1()  thread : "<<QThread::currentThreadId()<<endl;

}

接着创建一个对象,并调用:moveToThread ( QThread * targetThread ),让对象在新的线程中运行。

int main(int argc, char *argv[])

{

QCoreApplication a(argc, argv);

cout<<"mainthread :"<<QThread::currentThreadId()<<endl;

QThread thread;

Worker work;

thread.start();              //注意记得启动线程

work.moveToThread(&thread);

//由于不能直接调用worker

//的函数,所以一般用信号触发调用

QTimer::singleShot(0,&work,SLOT(fun1()));

QTimer::singleShot(0,&work,SLOT(fun1()));

returna.exec();

}

这样就能让fun1()和fun2()都运行在thread线程中了。

需要注意的是:在work 的函数结束运行前,thread不能被析构。Thread的生命期不能小于work。否则的话程序就好崩掉了。

像下面的代码肯定是不行的。

void Dialog::startWork()

{

QThread thread;

Worker*work = new Worker;

thread.start();

work->moveToThread(&thread);

QTimer::singleShot(0,work,SLOT(fun1()));

QTimer::singleShot(0,work,SLOT(fun2()));

}

所以thread 必须是new出来的。但是这样的话,就感觉有点麻烦,我们要同时管理thread和work,因为都是new 出来,我们需要负责清理。为了避免这样的麻烦,我想到的方法是,在work类中添加一个QThread成员。

class Worker:publicQObject

{

Q_OBJECT

public:

Worker();

~Worker();

protectedslots:

voidfun1();

voidfun2();

private:

QThread m_thread;

};

Worker::Worker():QObject()

{

m_thread.start();

this->moveToThread(&m_thread);

}

这样我们在用的时候只需要newwork就行了。

四、使用QtConcurrent::run

其实前面也有用到QtConcurrent::run启动新线程了。QtConcurrent命名空间提供了很多方法可以实现并发编程,这个以后再深入探讨了,这里只是大概讲一下启动线程。还是用上面的worker代码作为例子:

void Worker::start()

{

QtConcurrent::run(this,&Worker::fun1);

QtConcurrent::run(this,&Worker::fun2);

}

QtConcurrent::run是个模板函数,有很多种形式,我们也可以让全局的函数允许在另外的线程中。

void printMes(char*mes)

{

cout<<"pprintMes(char*mes)  thread : "<<QThread::currentThreadId()<<endl;

cout<<mes<<endl;

}

int main(int argc, char *argv[])

{

QCoreApplication a(argc, argv);

cout<<"mainthread :"<<QThread::currentThreadId()<<endl;

char *mes= "hello world";

QtConcurrent::run(printMes,mes);

returna.exec();

}

目前所知的新建线程的方法就大概这些了,希望对大家有用,可能还要别的,以后再继续学习了

http://blog.csdn.net/hai200501019/article/details/9899207

Qt新建线程的方法(有QRunnable,QThreadPool,moveToThread和QtConcurrent的例子)的更多相关文章

  1. Qt新建线程的方法(四种办法,很详细,有截图)

    看了不少Qt线程的东西,下面总结一下Qt新建一个线程的方法. 一.继承QThread 继承QThread,这应该是最常用的方法了.我们可以通过重写虚函数void QThread::run ()实现我们 ...

  2. Nuke中新建线程的方法

    最近维护合成部门的nuke工具包,发现不少工具的使用方法都很个人化,没有说明文档.这也导致artist在使用工具的时候比较感性,调整参数的时候缺少前后逻辑,长此以往,artist会产生这种意识:只要最 ...

  3. Winform用匿名方法新建线程的方法

    作用:1.将耗时的操作放在单独的线程,加快UI的响应速度.Thread t = new Thread(delegate() { parse.ParseDay(StockCode, FileName); ...

  4. 【QT】继承QRunnable+QThreadPool实现多线程

    往期链接: <QThread源码浅析> <子类化QThread实现多线程> <子类化QObject+moveToThread实现多线程> 本文章实例的源码地址:ht ...

  5. Java新建线程的3种方法

    Java新建线程的3种方法 =================== Java创建线程有3种方法:(1)继承Thread;(2)实现Runnable接口:(3)实现Callable接口; 由于Java只 ...

  6. java 在方法中新建线程,传参和加锁详解

    在实际开发中,往往在基本两三种创建线程的方法之外,还用到一个简单的创建线程调用方法的情况,代码如下: public void deleteRedisData(RedisKey redisKey){ n ...

  7. Qt经典—线程、事件与Qobject(耳目一新)

    介绍 You’re doing it wrong. — Bradley T. Hughes 线程是qt channel里最流行的讨论话题之一.许多人加入了讨论并询问如何解决他们在运行跨线程编程时所遇到 ...

  8. Qt经典—线程、事件与Qobject

    介绍 You’re doing it wrong. — Bradley T. Hughes 线程是qt channel里最流行的讨论话题之一.许多人加入了讨论并询问如何解决他们在运行跨线程编程时所遇到 ...

  9. Qt之线程基础

    何为线程 线程与并行处理任务息息相关,就像进程一样.那么,线程与进程有什么区别呢?当你在电子表格上进行数据计算的时候,在相同的桌面上可能有一个播放器正在播放你最喜欢的歌曲.这是一个两个进程并行工作的例 ...

随机推荐

  1. go语法之一

    Go语法: Go语言要求public的变量必须以 大写字母开头,private变量则以小写字母开头,这种做法不仅免除了public.private关键字,更重要的是统一了命名风格. Go语言对{  } ...

  2. URL中含有+号,出现错误“请求筛选模块被配置为拒绝包含双重转义序列的请求”的解决方法

    搜索关键词中含空格,提交后被自动转成了“+”号,报如下错误: HTTP 错误 404.11 - Not Found 请求筛选模块被配置为拒绝包含双重转义序列的请求. 解决方法: 在web.config ...

  3. 在mysql中创建存储过程出现1307错误,解决方法

    需要删除mysql数据库下proc表 在重新创建 CREATE TABLE `proc` ( `db` char(64) character set utf8 collate utf8_bin NOT ...

  4. ASP.NET Calendar 控件

    ASP.NET Calendar 控件 http://www.w3school.com.cn/aspnet/control_calendar.asp

  5. 如何在UILable上添加点击事件?

    最近开始学习iOS开发,今天上来写第一个iOS笔记 昨天碰到一个需求,在UILable上添加点击事件,网上找了写资料,有人建议用透明的UIButton覆盖,有人建议写一个集成自UILable的类,扩展 ...

  6. CSS: inline-block的应用和float块高度塌陷

    普通流高度塌陷: 当块float浮动时,不会对块布局产生影响,块仍然会按照左右或者上下的顺序排列.但是会影响文档的排列,当文档的高度超过块的高度时,块的高度会产生塌陷现象.   高度塌陷解决方法:   ...

  7. Spring源码地址和相关介绍的网址

    Spring源码地址下载: https://github.com/spring-projects/spring-framework/tags >多图详解Spring框架的设计理念与设计模式:ht ...

  8. php返回的json格式

    public function search_ip(){ $where['ip'] = $_GET['ip']; $Machine = M('Machine_info'); $arr = $Machi ...

  9. IT第十九天 - 继承、接口、多态、面向对象的编程思想

    IT第十九天 上午 继承 1.一般情况下,子类在继承父类时,会调用父类中的无参构造方法,即默认的构造方法:如果在父类中只写了有参的构造方法,这时如果在子类中继承时,就会出现报错,原因是子类继承父类时无 ...

  10. Java学习之开篇—个人随想

    现在大三上学期了,家里希望考研,不然觉得我这学校不好找工作,我自己觉得工作还是靠自己,学校就像给人第一眼感觉那样,虽然重要但也只会吸引HR多看两眼,真正留得住HR的还是要有拿的出手的技能. 当初凭着对 ...