QT线程与定时器[二]

2014-08-14  来源:本站原创  分类:Qt  人气:5 

下面转一个相关说明吧

实例代码1:

class MThread :public QThread
{
public:
    MThread();
    ~MThread();
    virtual void run();
    void foo();
    ...
};

POINT 1:QThread类的实例与普通类的实例没什么不同,只是运行着的run()函数会不同

实例代码2:

class MDialog :public QDialog
{
    ...
    MThread *mythread;
};
MDialog::MDialog()
{
   mythread = new MThread;
   ...
}

需要注意的是,在QT中,QThread对象的实例mythread是属于创建它的线程(线程A,即MDialog所在的线程)的,mythread的所有程序代码与数据都放在与MDialog相同的空间中.这时的mythread,就像任何普通的自己定义的类的实例一样.但是在调用mythread->start()之后,mythread的run()函数中的代码会在新的线程(线程B)中执行.在run()函数中声明的变量\实例化的对象,都属于线程B.但是mythread的所有代码,都还在存储在线程A中,只是run()函数的"执行"是在线程B中.

在MDialog中,使用

mythread->foo();
foo()是在线程A中执行的.

在MDialog中使用

connect(this, SIGNAL(sigDialogSignal()), mythread, SLOT(slotThreadSlot()));

当emit sigDialogSignal()时,是会在MDialog所在的线程A中执行的.因为mythread与MDialog同属于一个线程, 这时thread可以看做一个普通类的实例.另外,因为connect函数的连接方式默认是自动连接,而对同属于一个纯种的两个对象,自动连接会使用直接连接,即slot在发出signal的线程中立即执行.

实例代码3:

#include "mthread.h"
#include <QDebug>
MThread::MThread(QObject *parent)
    : QThread(parent)
{
    myTimer.start(1);
    connect(&myTimer, SIGNAL(timeout()), this, SLOT(slotPrint()));
}  

MThread::~MThread()
{  

}  

void MThread::run()
{
    for (int i = 0; i < 100; ++i) {
       for (int j = 0 ; j < 10000; ++j) {
            qDebug()<<"---------"<<i;
        }
    }
    exec();
}  

void MThread::slotPrint()
{
   qDebug()<<"==============================";
}

运行后出现:
...
...
---------9
==============================================================
---------9
...
...

不能误以为:在一个QThread类的派生类中,run()函数中的语句在运行时,可能被本线程定时器超时slot中断. (错误)

事实上,slotPrint()在创建MThread的实例的线程中执行,而run()函数在新的线程中运行。

POINT 2:线程B中的对象要想接收线程A中的对象发来的signal, 必须进入exec(), 如在exec()前有死循环, 没有进入exec(), 则线程B中的对象不会收到signal.

实例代码4:

void MThread::run()
{
    while(1) {
        dosomething();  //此循环永不退出
    }
    exec();             //如果此事件循环不能进入,刚此线程不会收到任何signal
}

POINT 3:线程A中的指针可指向线程B中创建的对象实例, 这个实例属于线程B. 指针仅仅是一个地址, 而对象实例的变量/代码等都属于线程B.

实例代码5:

class MThread : public QThread
{
    Q_OBJECT  

public:
    MThread(QObject *parent = 0);
    ~MThread();
    void run();
    MPrint *mprint;
};
void MThread::run()
{
    mprint = new MPrint;
    exec();
}
//如此声明,mprint所指向的对象属于另一个线程,即原始线程.
实例代码6:
class MThread : public QThread
{
    Q_OBJECT  

public:
    MThread(QObject *parent = 0);
    ~MThread();
    void run();
    MPrint *mprint;
private:
    QTimer *myTimer;  

private slots:
    void slotPrint();
    void testFoo();
};  

void MThread::run()
{
    myTimer = new QTimer;
    mprint = new MPrint;
    myTimer->setInterval(100);
    connect(myTimer, SIGNAL(timeout()), this, SLOT(testFoo()), Qt::DirectConnection);
    QTimer::singleShot(0, myTimer,SLOT(start()));
    exec();
}

以上这样写run(),myTimer在run()中new,即myTimer这个指针属于旧线程,但myTimer所指向的QTimer实例的实体在新的线程中,testFoo()会在新线程中执行.

实例代码7:

void MThread::run()
{
    QTimer myTimer;
    mprint = new MPrint;
    myTimer.setInterval(100);
    connect(&myTimer, SIGNAL(timeout()), this, SLOT(testFoo()), Qt::DirectConnection);
    QTimer::singleShot(0, &myTimer,SLOT(start()));
    //testFoo();
    exec();
}

以上这样写run(),myTimer在run()中声明,即myTimer属于新的线程,testFoo()也会在新线程中执行.

实例代码8:
class MThread : public QThread
{
    Q_OBJECT  

public:
    MThread(QObject *parent = 0);
    ~MThread();
    void run();
    MPrint *mprint;
private:
    QTimer myTimer;  

private slots:
    void slotPrint();
    void testFoo();
};  

void MThread::run()
{
    mprint = new MPrint;
    myTimer.setInterval(100);
    connect(&myTimer, SIGNAL(timeout()), this, SLOT(testFoo()));
    QTimer::singleShot(0, &myTimer,SLOT(start()));
    //testFoo();
    exec();
}

以上这样写run(),testFoo()会在创建myTimer的老线程中执行.因为可以看到,mytimer和this(即mythread),都是在同一个线程中,只是在另一个线程中(run()),做了connect操作.

要注意的是,在线程B中启动线程A中的一个定时器,不能使用

myTimer.start(),这样启动不了定时器.而应使用signal来触发start()这个slot.

POINT 5:slot不会中断同线程中的slot.

实例代码8:

#include "mthread.h"
#include <QDebug>
MThread::MThread(QObject *parent)
    : QThread(parent)
{
    myTimer.start(1);
    connect(&myTimer, SIGNAL(timeout()), this, SLOT(slotPrint()));
}  

MThread::~MThread()
{  

}  

void MThread::run()
{
    exec();
}  

void MThread::slotPrint()
{
    qDebug()<<"===========================";
    for (int i = 0; i < 100; ++i) {
        for (int j = 0 ; j < 10000; ++j) {
            qDebug()<<"---------"<<i;
        }
    }
}

slotPrint()函数运行完之后才会退出,说明slot不会中断slot,一个slot在执行完之后才会执行下一个slot.

注意:slotPrint()在创建MThread实例的线程中执行.而不是使用thread->start()创建出的那个线程.

实例代码8:

#include "mthread.h"
#include <QDebug>
MThread::MThread(QObject *parent)
    : QThread(parent)
{
    myTimer.start(1);
    connect(&myTimer, SIGNAL(timeout()), this, SLOT(slotPrint()));
}  

MThread::~MThread()
{  

}  

void MThread::run()
{
    testFoo();
    exec();
}  

void MThread::slotPrint()
{
    qDebug()<<"=======================";  

}  

void MThread::testFoo()
{
    for (int i = 0; i < 100; ++i) {
        for (int j = 0 ; j < 10000; ++j) {
            qDebug()<<"---------"<<i;
        }
    }
}

以上代码中,slotPrint()与testFoo()会在两个不同的线程中执行.

相关文章
  • QT线程与定时器[二] 2014-08-14

    下面转一个相关说明吧 实例代码1: class MThread :public QThread { public: MThread(); ~MThread(); virtual void run(); void foo(); ... }; POINT 1:QThread类的实例与普通类的实例没什么不同,只是运行着的run()函数会不同 实例代码2: class MDialog :public QDialog { ... MThread *mythread; }; MDialog::MDialog

  • Qt线程和定时器[一] 2014-08-14

    新的线程run里面一定要有exec的调用,否则无法接受消息的. class myQThr : public QThread { Q_OBJECT public: myQThr(QObject *in = NULL) :QThread(in) { WrTimer = new QTimer(this); connect(WrTimer, SIGNAL(timeout()), this, SLOT(TimerOutWr1()), Qt::DirectConnection); WrTimer->star

  • Qt 线程基础(QThread.QtConcurrent.QThreadPool等) 2012-11-08

    使用线程 基本上有种使用线程的场合: 通过利用处理器的多个核使处理速度更快. 为保持GUI线程或其他高实时性线程的响应,将耗时的操作或阻塞的调用移到其他线程. 何时使用其他技术替代线程 开发人员使用线程时需要非常小心.启动线程是很容易的,但确保所有共享数据保持一致很难.遇到问题往往很难解决,这是由于在一段时间内它可能只出现一次或只在特定的硬件配置下出现.在创建线程来解决某些问题之前,应该考虑一些替代的技术 : 替代技术 注解 QEventLoop::processEvents() 在一个耗时的计

  • qt线程----部分代码片段 2012-11-09

    一.把视频显示到界面的方法 (1)针对qt4的(视频格式为rgb32) v4l_grab_movie(&v4l_dev); unsigned char *pBuffer= v4l_dev.buffer; QImage image(pBuffer,320,240,QImage::Format_RGB32); QPixmap pixmap; pixmap=pixmap.fromImage(image); label->setPixmap(pixmap); label->setFixedSi

  • Qt 线程基础(QThread.QtConcurrent等) 2012-11-10

    昨晚看Qt的Manual,突然发现下一个版本的Qt中(Qt4.7.4.Qt4.8等)增加了一个特赞的介绍多线程的文章 : Thread Basics 注意: 该链接以后会失效,但是 到时候你直接看Qt自带Manual就行了 本文不是严格的翻译 dbzhang800 2011.06.18 使用线程 基本上有种使用线程的场合: 通过利用处理器的多个核使处理速度更快. 为保持GUI线程或其他高实时性线程的响应,将耗时的操作或阻塞的调用移到其他线程. 何时使用其他技术替代线程 开发人员使用线程时需要非常

  • python通过线程实现定时器timer的方法 2014-06-04

    这篇文章主要介绍了python通过线程实现定时器timer的方法,涉及Python线程与定时器timer的使用技巧,需要的朋友可以参考下 本文实例讲述了python通过线程实现定时器timer的方法.分享给大家供大家参考.具体分析如下: 这个python类实现了一个定时器效果,调用非常简单,可以让系统定时执行指定的函数 下面介绍以threading模块来实现定时器的方法. 使用前先做一个简单试验: import threading def sayhello(): print "hello wor

  • Qt线程基础(这个比较完整) 2012-11-09

    线程基础 保谓线程? 线程与并行处理任务息息相关,就像进程一样.那么,线程与进程有什么区别呢?当你在电子表格上进行数据结算的时候,在相同的桌面上可能有一个播放器正在播放你最喜欢的歌曲.这是一个两个进程并行工作的例子:一个进程运行电子表格程序;另一个进程运行一个媒体播放器.这种情况最适合用多任务这个词来描述.进一步观察媒体播放器,你会发现在这个进程内,又存在并行的工作.当媒体播放器向音频驱动发送音乐数据的时候,用户界面上与之相关的信息不断地进行更新.这就是单个进程内的并行线程. 那么,线程的并行性

  • Qt 中的多线程(二) 2015-05-03

    可重入与线程安全 在Qt文档中,术语"可重入"与"线程安全"被用来说明一个函数如何用于多线程程序.假如一个类的任何函数在此类的多个不同的实例上,可以被多个线程同时调用,那么这个类被称为是"可重入"的.假如不同的线程作用在同一个实例上仍可以正常工作,那么称之为"线程安全"的. 大多数c++类天生就是可重入的,因为它们典型地仅仅引用成员数据.任何线程可以在类的一个实例上调用这样的成员函数,只要没有别的线程在同一个实例上调用这个成员

  • android进程与线程详解二:线程 2012-03-12

    线程 当一个应用被启动,系统创建一个执行线程,叫做"main".这个线程是十分重要的,因为它主管向用户界面控件派发事件.其中包含绘图事件.它也是你的应用与界面工具包(android.widget和 android.view包中的组件)交互的地方.于是main线程也被称为界面线程. 系统不会为每个组件的实例分别创建线程.所有运行于一个进程的组件都在界面线程中被实例化,并且系统对每个组件的调用都在这个线程中派发. 结果,响应系统调用的方法(比如报告用户动作的onKeyDown()或一个生命

  • QT定时器QTimer 2012-10-29

    在Qt中使用定时器有两种方法,一种是使用QObiect类的定时器:一种是使用QTimer类.定时器的精确性依赖于操作系统和硬件,大多数平台支持20ms的精确度. 1.QObject类的定时器 QObject是所有Qt对象的基类,它提供了一个基本的定时器.通过QObject::startTimer(),可以把一个一毫秒为单位的时间间隔作为参数来开始定时器,这个函数返回一个唯一的整数定时器的标识符.这个定时器开始就会在每一个时间间隔"触发",直到明确的使用这个定时器的标识符来调用QObje

  • Qt下几个线程函数介绍 2012-11-09

    1.QCoreApplication::processEvents() 2.每个线程可以有它的事件循环,初始线程开始它的事件循环需使用QCoreApplication::exec(),别的线程开始它的事件循环需要用QThread::exec().像QCoreApplication一样,QThreadr提供了exit(int)函数,一个quit() slot. 线程安全的函数QCoreApplication::postEvent(),在任何时候,给任何线程中的任何对象投递一个事件,事件会在那个创建

  • Qt中的多线程编程 2010-08-18

    Qt中的多线程编程 级 别: 初级 续欣 ([email protected]), 2004 年 4 月 01 日 Qt 作为一种基于 C++ 的跨平台 GUI 系统,能够提供给用户构造图形用户界面的强大功能.为了满足用户构造复杂图形界面系统的需求,Qt 提供了丰富的多线程编程支持. Qt 作为一种基于 C++ 的跨平台 GUI 系统,能够提供给用户构造图形用户界面的强大功能.为了满足用户构造复杂图形界面系统的需求,Qt 提供了丰富的多线程编程支持.从 2.2 版本开始,Qt 主要从下面三个方

  • Qt 中的多线程(一) 2014-04-24

    QT通过三种形式提供了对线程的支持.它们分别是,一.平台无关的线程类,二.线程安全的事件投递,三.跨线程的信号-槽连接.这使得开发轻巧的多线程Qt程序更为容易,并能充分利用多处理器机器的优势.多线程编程也是一个有用的模式,它用于解决执行较长时间的操作而不至于用户界面失去响应.在Qt的早期版本中,在构建库时有不选择线程支持的选项,从4.0开始,线程总是有效的. 线程类 Qt 包含下面一些线程相关的类: QThread 提供了开始一个新线程的方法 QThreadStorage 提供逐线程数据存储 Q

  • Qt的多线程编程注意事项 2014-04-01

    QT总的来说是一个易学易用的库, 但是QT的多线程使用确实容易犯错,尤其是结合上异步的网络访问,谁用谁知道.我觉得核心是一句话,QThread要当作线程控制块用,不要以为派生一个QThread的子类,里面的东西都跑在新的线程里了,只有run()里的是这样. 下面这篇文章我觉得讲的很好,深入解析QT的线程用法,文章有点长,但是值得一读. 原文在 http://qt-project.org/wiki/ThreadsEventsQObjects 译文在 http://www.cppblog.com/b

  • JAVA线程用法详解 2013-12-11

    这篇文章主要介绍了JAVA线程用法,配合实例针对Java中线程的开启.sleep.合并与让出等进行了较为深入的分析,需要的朋友可以参考下 本文配合实例较为详细的讲解了Java的线程技术,相信对于深入理解Java程序设计有一定的帮助.具体如下: 很多人在学习JAVA时都对线程都有一定的了解,而当我们开始接触Android开发时,才真真正正的发现了线程是多麽的重要,本文就把对Java线程的用法心得分享给大家,供大家参考. 首先,大家一定要分清线程和进程不是一回事,进程是什么呢?进程就如我们需要执行c

  • 白话并发冲突与线程同步(2)--Monitor.lock和死锁 2013-12-08

    系列文章汇总:白话并发冲突与线程同步(1) 白话并发冲突与线程同步(2)--Monitor.lock和死锁 白话并发冲突与线程同步(3)--Mutex.EventWaitHandle.AutoResetEvent 和 ManualResetEvent 竞赛暂时胜过它的目的,永远如此.对于要建立殖民地的殖民主义者,生活的意义就在于征服.士兵看不起移民,但是,征服的目的不就是要让移民定居下来吗?因此,在进步的狂热中,我们把人招来修铁路,建工厂,钻油井.但是,我们不是记得很清楚,我们进行的这些建设是服

  • ACE线程管理 2012-03-09

    运用ACE_Thread_Manager类创建线程 创建线程需要要解决两个问题,一是调用线程函数,二是提供一个途径让线程能够访问到外部传递过来的参数.下面的代码演示了基本的用法: #include <stdexcept> #include "ace/ACE.h" #include "ace/Log_Msg.h" #include "ace/Thread_Manager.h" #include <map> #include

  • Java多线程一(基础及线程状态转换) 2013-03-17

    Java实现多线程的方法有两种,一是继承Thread类.二是实现Runnable接口. 一.继承Thread类 public class ThreadTest extends Thread { @Override public void run() { System.out.println("this thread name is:"+Thread.currentThread().getName()); } /** * @param args */ public static void

  • 多线程编程(四)--线程终止 2013-08-30

    如果进程中的任一线程调用了exit, _Exit或_exit,则整个进程就会终止.另外,如果信号的默认动作也是终止进程,那么把该信号发送到线程也会终止整个进程. 单个线程可通过以下三种方式退出,在不终止整个进程的情况下停止它的控制流. 1.线程只是从启动例程中返回,返回值是线程的退出码. 2.线程可以被同一进程中的其他线程取消 . 3.线程调用pthread_exit退出. (一)线程退出 #include <pthread.h> void pthread_exit(void *value_p

  • 一个MIDP俄罗斯方块游戏的设计和实现 2014-09-02

    文章来源:csdn 作者:陈万飞 作者简介 陈万飞,男,中南大学数软系学士,曾任北京长城软件高级程序员,系统分析师.有较为丰富的j2se,j2ee开发经验.目前致力于j2me研究工作.可通过[email protected]与他联系 摘要 本文给出了一个基于MIDP1.0的俄罗斯方块游戏的设计方案,并给出全部实现源代码.该游戏的最大特色是屏幕自适应,无论各种手机,PDA的屏幕大小如何,该游戏总是能获得最佳的显示效果.游戏在J2me wireless toolkit 2.1的4种模拟器上测试通过.