看了不少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新建线程的方法(四种办法,很详细,有截图)的更多相关文章

  1. Qt新建线程的方法(有QRunnable,QThreadPool,moveToThread和QtConcurrent的例子)

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

  2. js检测数据类型四种办法

    面试题中经常会考js数据类型检测,今天我来分享一下js中常用的四种方法判断数据类型,欢迎指点更正. 废话不多说,直入正题. 1.typeof console.log(typeof "&quo ...

  3. Java-五种线程池,四种拒绝策略,三种阻塞队列(转)

    Java-五种线程池,四种拒绝策略,三种阻塞队列 三种阻塞队列:    BlockingQueue<Runnable> workQueue = null;    workQueue = n ...

  4. 线程终止的四种方式,interrupt 方法使用的简单介绍。

    一 正常结束. package com.aaa.threaddemo; /* 一 终止线程的四种方式? * 程序运行结束,线程终止. * */ public class ThreadTerminati ...

  5. java并发编程(四)守护进程 线程阻塞的四种情况

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17099981 守护线程   Java中有两类线程:User Thread(用户线程).Da ...

  6. 转:【Java并发编程】之四:守护线程与线程阻塞的四种情况

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17099981      守护线程   Java中有两类线程:User Thread(用户线 ...

  7. C++线程同步的四种方式(Windows)

    为什么要进行线程同步? 在程序中使用多线程时,一般很少有多个线程能在其生命期内进行完全独立的操作.更多的情况是一些线程进行某些处理操作,而其他的线程必须对其处理结果进行了解.正常情况下对这种处理结果的 ...

  8. java线程实现的四种方式

    java多线程的实现可以通过以下四种方式 1.继承Thread类,重写run方法 2.实现Runnable接口,重写run方法 3.通过Callable和FutureTask创建线程 4.通过线程池创 ...

  9. 【Java并发编程】:守护线程与线程阻塞的四种情况

    守护线程 JAVA中有两类线程:User Thread(用户线程).Daemon Thread(守护线程) 用户线程即运行在前台的线程,而守护线程是运行在后台的线程. 守护线程作用是为其他前台线程的运 ...

随机推荐

  1. [Head First Python]1. 初始python-人人都爱列表

    movies = [ "hello", "world",["xin","lover",["Jerry" ...

  2. js禁止中文输入 最简洁的【禁止输入中文】

    方法一:禁止中文输入法 <input type="text"  > 方法二:禁止黏贴,禁止拖拽,禁止中文输入法! 这种方法是最强的禁止 中文输入 <input t ...

  3. oracle全文检索笔记

    1.删除词法解析器 exec ctx_ddl.drop_preference('my_lexer'); 2.创建中文词法解析器 exec ctx_ddl.create_preference ('my_ ...

  4. EntityFramework+Autofac+MVC+EasyUI 搭建公司基本服务项目

    去年年底用了2个星期的时间搭建了 这套框架,从ORM,IOC,MVC,EasyUI都仔细的研究了下,还有日志,异常等等.mvc 我已经开发过很多项目了,我就觉得自己写套框架,看看自己的水平如何.欢迎大 ...

  5. Sql Server专题一:索引(中)

    写在前面的废话: 索引这个知识点,我前前后后不知道看了多少边,网上的文章五花八门,搞的我晕头转向,搞的牛逼点的就是测试索引带来的好处,还搞一大堆的测试数据出来,有意思吗?MS自己不会测试吗?这样的测试 ...

  6. 使用LINQ来简化编程的7个技巧

    转载地址:http://www.cnblogs.com/lovecherry/archive/2008/05/23/1205565.html 自从学习LINQ以来,我发现了很多使用LINQ来改善代码的 ...

  7. JVM启动过程——JVM之一

    JVM是Java程序运行的环境,同时是一个操作系统的一个应用程序进程,因此它有自己的生命周期,也有自己的代码和数据空间. JVM体系主要是两个JVM的内部体系结构分为三个子系统和两大组件,分别是:类装 ...

  8. 【Xamarin挖墙脚系列:Xamarin正式发布了IOS的模拟器在Windows下】

    xamarin 的发展越来越迅速.如果还感觉这玩意儿是个鸡肋,辣么请跟的上时代吧 . (额,对微软产品有严重偏见的请绕行..............其实你可以看看.net 基金会现有的开源项目再说不开 ...

  9. OpenFileDialog 害人的RestoreDirectory

    莫名其妙出现找不到文件的错误.经查,发现: OpenFileDialog,SaveFileDialog在选择文件后,会切换当前程序目录的路径(System.Environment.CurrentDir ...

  10. Pasha and Phone(思维)

    Pasha and Phone time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...