• 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

  • 相关阅读:
    文件操作相关utils
    读取excel工具utils
    下载EXCEL文件Utils
    日期操作utils
    常用的utils
    坐标系转换Utils
    C# vs2019 CS0006 编译器错误CS1704
    C# 控制台形式 owin 添加WebApi 和Swagger
    Windows 下 Redis服务自动停止 处理
    Dotfuscator 混淆C# .Net代码 netcore
  • 原文地址:https://www.cnblogs.com/findumars/p/5176140.html
Copyright © 2020-2023  润新知