Qt线程QThread简析(8个线程等级,在UI线程里可调用thread->wait()等待线程结束,exit()可直接退出线程,setStackSize设置线程堆栈,首次见到Qt::HANDLE,QThreadData和QThreadPrivate)
QThread实例代表一个线程,我们可以重新实现QThread::run(),要新建一个线程,我们应该先继承QThread并重新实现run()函数。
需要注意的是:
1.必须在创建QThread对象之前创建 QApplication (或QCoreApplication)对象。
2. QCoreApplication::exec() 必须只能从主线程调用,不能从QThread线程调用。
class MyThread : public QThread
{
Q_OBJECT
public:
MyThread(QObject *parent = NULL);
~MyThread();
protected:
voidrun();
};
void MyThread::run()
{
for( int count = 0; count < 20; count++ )
{
sleep( 1 );
}
qDebug( "finish!");
}
我们可以在另外的函数这样调用:
MyThread thread;
thread.start();
thread.wait(); //必须要加的语句,等待thread结束。
当然我们先开的线程可能是要运行很久,会卡住主线程,使用QeventLoop就可以轻松解决此类问题:
MyThread thread;
thread.start();
QeventLoop;
connect(&thread,SIGNAL(finished ()),&eventLoop,SLOT(quit()));
thread.wait(1);
eventLoop.exec();
接下来我们看QThread的其他属性和函数:
Qthread的优先级属性:Priority指示系统如何调度线程。
|
Constant |
Value |
Description |
|
QThread::IdlePriority |
0 |
scheduled only when no other threads are running. |
|
QThread::LowestPriority |
1 |
scheduled less often than LowPriority. |
|
QThread::LowPriority |
2 |
scheduled less often than NormalPriority. |
|
QThread::NormalPriority |
3 |
the default priority of the operating system. |
|
QThread::HighPriority |
4 |
scheduled more often than NormalPriority. |
|
QThread::HighestPriority |
5 |
scheduled more often than HighPriority. |
|
QThread::TimeCriticalPriority |
6 |
scheduled as often as possible. |
|
QThread::InheritPriority |
7 |
use the same priority as the creating thread. This is the default. |
0到6的优先级跟windows线程相对应的,就多了一个InheritPriority。
非静态成员函数:
|
void |
exit ( int returnCode = 0 ) |
该函数告诉线程退出事件循环和返回代码returnCode ;通常返回0意味着成功,非0意味着错误。
需要注意的是,该函数不像C语言的库函数exit一样返回到调用者。除非再次调用QThread::exec(),否则不会再执行任何事件循环。如果QThread::exec()的事件循环没有运行,接着的QThread::exec()将会立即返回。
这两个函数看名字就知道意思:
bool QThread::isFinished ()const
如果线程结束,则返回true,否则返回false。
bool QThread::isRunning ()const
如果线程还在运行则返回true,否则返回false
void QThread::setPriority ( Priority priority )
该函数设置了正在运行的线程的优先级。如果线程没有运行,函数什么也不做,直接返回。跟踪源码发现setPriority 的源码部分如下:
if(!d->running)
{
qWarning("QThread::setPriority:Cannot set priority, thread is not running");
return;
}
如果线程没有运行,函数只输出一个警告便返回了。
需要注意的是:参数不能是InheritPriorty。
case InheritPriority:
default:
qWarning("QThread::setPriority:Argument cannot be InheritPriority");
return;
如果是InheritPriorty,函数也只输出一个警告便返回了。
优先级参数的影响依赖于操作系统的调度策略。特别是,在不支持线程优先级的系统(如linux)优先级参数将被忽略。
void QThread::setStackSize ( uint stackSize )
该函数设置线程堆栈的最大值。
需要注意的是:
1.必须在线程启动之前设置
2. 虽然参数是uint类型,传入负数的话会自动转换。
3.大部分的操作系统都设置了线程堆栈的最大最小值限制。如果超出了限制线程可能运行失败。
验证了一下,当我传-1进去,stackSize值变成了4294967295。Start函数里调用beginthreadex创建新线程。Beginthreadex里调用CreateThread这是大部分用过windows多线程的程序员都了解的。创建失败则输出警告并返回。
d->handle = (Qt::HANDLE)_beginthreadex(NULL, d->stackSize, QThreadPrivate::start,
this, CREATE_SUSPENDED, &(d->id));
if(!d->handle) {
qErrnoWarning(errno, "QThread::start: Failed to create thread");
d->running = false;
d->finished = true;
return;
}
uint QThread::stackSize () const
该函数返回线程堆栈最大值,如果调用setStackSize()设置最大值的话,返回的就是设置的值,否则返回0;
bool QThread::wait ( unsigned long time =ULONG_MAX )
该函数阻塞线程直到满足以下条件之一;
1. 线程已经执行结束。如果线程结束,该函数返回true。如果线程没被启动也会返回true。
2. Time毫秒时间过去了。如果time 为 ULONG_MAX,该函数永远不会超时。如果超时,函数返回false。
槽函数:
void QThread::quit ()
函数退出事件循环,返回代码为0.与调用exit(0).一样的效果。如果线程没有事件循环则什么也不做。
void QThread::start ( Priority priority =InheritPriority ) [slot]
通过调用开始run(),执行线程。如果线程已经在运行,则什么也不做。
看一下源码:
Start()调用:
d->handle =(Qt::HANDLE) _beginthreadex(NULL, d->stackSize, QThreadPrivate::start, this,CREATE_SUSPENDED, &(d->id));
创建线程。
unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSEQThreadPrivate::start(void *arg)
{
QThread *thr = reinterpret_cast<QThread*>(arg);
QThreadData *data = QThreadData::get2(thr);
。。。。。
。。。。。。 //中间省略,删掉了
emitthr->started(); //发送started信号。
QThread::setTerminationEnabled(true);
thr->run(); //运行我们重新实现的代码。
finish(arg); //该函数发送finished();信号。
return 0;
}
void QThread::terminate ()
终止线程的运行。线程可能不会理解被终止,这依赖于操作系统的调用策略。在terminate()之后调用QThread::wait()同步终止。
终止线程之后,所有等待线程结束的线程都会被唤醒。
void QThread::terminate()
{
Q_D(QThread);
QMutexLocker locker(&d->mutex);
if(!d->running)
return;
if(!d->terminationEnabled) {
d->terminatePending = true;
return;
}
TerminateThread(d->handle, 0);
d->terminated = true;
QThreadPrivate::finish(this, false); //finish函数发送了finished()信号。从而会唤醒所有等待的线程。
}
除非真的有必要,不然不要轻易调用该函数。
QThread * QThread::currentThread ()
函数返回当前正在执行的线程。
Qt::HANDLE QThread::currentThreadId ()
注意:
返回当前运行的线程的句柄。该函数返回的句柄只能内部使用,不能在其他任何程序的代码中使用。
在windows系统,该返回值是当前线程的伪句柄。不能用作数值比较,函数返回Win32 函数 getCurrentThreadId()返回的DWORD值。而不是 Win32 函数 getCurrentThread()返回的HANDLE值。
int QThread::idealThreadCount ()
函数返回系统可以运行的理想的线程数。
int QThread::idealThreadCount()
{
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
returnsysinfo.dwNumberOfProcessors; //返回系统中的处理器的数目。
}
void QThread::yieldCurrentThread ()
放弃当前线程转到另外可执行的线程,有系统决定转到哪个线程。
void QThread::sleep ( unsigned long secs )
void QThread::msleep ( unsigned long msecs )
void QThread::usleep ( unsigned long usecs )
这三个函数是让线程进入休眠状态。它们内部都是调用了windows API Sleep。
void QThread::setTerminationEnabled ( bool enabled =true )
设置是否可以终止当前线程。
http://blog.csdn.net/hai200501019/article/details/9535069
Qt线程QThread简析(8个线程等级,在UI线程里可调用thread->wait()等待线程结束,exit()可直接退出线程,setStackSize设置线程堆栈,首次见到Qt::HANDLE,QThreadData和QThreadPrivate)的更多相关文章
- C#线程状态简析
在C# 语言世界中,当我们创建一个新的子线程,该线程状态为unstarted, 子线程开始之后,子线程状态为Running,IsAlive 为true: 线程响应 Thread.Start 并开始运行 ...
- nodejs全局对象简析
Global:全局变量 定时器.控制台输出.事件 模块化相关的一些全局变量 path/url相关的一些全局变量 编码相关的 buffer:缓存(简单介绍) Process:进程(重点解析) 一.Glo ...
- Thread类的常用方法_获取线程名称的方法和设置线程名称的方法
Thread类的常用方法 获取线程的名称: 1.使用Thread类中的方法getName() String getName() 返回该线程的名称 2.可以先获取到当前正在执行的线程,使用线程中的方法g ...
- C# 线程池ThreadPool的用法简析
https://blog.csdn.net/smooth_tailor/article/details/52460566 什么是线程池?为什么要用线程池?怎么用线程池? 1. 什么是线程池? .NET ...
- Java多线程简析——Synchronized(同步锁)、Lock以及线程池
Java多线程 Java中,可运行的程序都是有一个或多个进程组成.进程则是由多个线程组成的.最简单的一个进程,会包括mian线程以及GC线程. 线程的状态 线程状态由以下一张网上图片来说明: 在图中, ...
- 并发系列(一)——线程池源码(ThreadPoolExecutor类)简析
前言 本文主要是结合源码去线程池执行任务的过程,基于JDK 11,整个过程基本与JDK 8相同. 个人水平有限,文中若有表达有误的,欢迎大伙留言指出,谢谢了! 一.线程池简介 1.1 使用线程池的优点 ...
- 在不开启事件循环的线程中使用QTimer(QThread::run函数自带事件循环,在构造函数里创建线程,是一种很有意思的线程用法) good
引入 QTimer是Qt自带的定时器类,QTimer运行时是依赖于事件循环的,简单来说,在一个不开启事件循环(未调用exec() )的线程中,QTimer是无法使用的.通过分析Qt源码可发现,调用QT ...
- pyqt4:在线程Qthread中使用定时器Qtimer
GUI main 部分,主app类中的__init__初始化方法中添加 实例化线程 self.s2_thread=Worker2() 初始化一个定时器 self.log_get=QtCore.QTim ...
- Android -- 多媒体播放之MediaPlayer使用内部实现简析
Android -- MediaPlayer内部实现简析 在之前的博客中,已经介绍了使用MediaPlayer时要注意的内容.如今,这里就通过一个MediaPlayer代码实例,来进一步分析Media ...
随机推荐
- UC/0S2之基础总结
堆栈,就是在存储器中按数据“后进先出(LIFO)[类比杯子]”的原则组织的连续存储空间,为了满足任务切换和响应中断保存CPU寄存器中的内容及存储任务私有数据的需要,每个任务都应该配有自己的堆栈, 注意 ...
- 在ASP.NET中动态加载内容(用户控件和模板)
在ASP.NET中动态加载内容(用户控件和模板) 要点: 1. 使用Page.ParseControl 2. 使用base.LoadControl 第一部分:加载模板 下 面是一个模板“<tab ...
- MapReduce的C#实现及单元测试(试验)
MapReduce.cs类文件代码 MapReduce的执行方法 using System; using System.Collections.Generic; //using System.Lin ...
- C++学习之虚继承
http://blog.csdn.net/wangxingbao4227/article/details/6772579 C++中虚拟继承的概念 为了解决从不同途径继承来的同名的数据成员在内存中有不同 ...
- JAVA语言的素数判断,随机数,函数调用
近来刚学JAVA,就从JAVA写起吧,JAVA判别素数,其实方法和C/C++没什么区别,主要就是想谈一下,其中包括的3个点. (1)JAVA语言产生随机数,random函数,定义参数max的作用是给出 ...
- django1.6.x(python3.3)使用pymysql连接mysql
1.安装 pymysql,地址:https://code.google.com/p/pymysql/ 2.安装django 然后执行 django-admin.py startproject mysi ...
- HTML5 按字母顺序排列的标签列表 new : HTML5 中的新标签。
标签 描述 <!--...--> 定义注释. <!DOCTYPE> 定义文档类型. <a> 定义超链接. <abbr> 定义缩写. <acron ...
- 复制virtualenv环境到其他服务器环境配置的方法
要在n多服务器端部署python的应用,虽然python本身是跨平台的,当时好多第三方的扩展却不一定都能做到各个版本兼容,即便是都是linux,在redhat系列和ubuntu系列之间来回导也是个很让 ...
- Appium+Python app自动化测试之脚本启动和停止Appium服务
研究了一段时间的Appium android app的自动化测试,工作中需要连接多台手机终端同时执行测试用例,我实现的方式是获取用例中需要执行用例的设备id个数以及实际连接到的设备数(通过adb de ...
- 省部级干部list
省部级干部表 省(市.自治区) 省(市)委书记 省(市)人大主任 省(市)长 省(市)政协主席 北京市 郭金龙 杜德印 王安顺 吉林 天津市 黄兴国 肖怀远 黄兴国 臧献甫 上海市 韩正 殷一璀(女) ...