QThread Class


QThread class

标准头文件:#include <QThread>
qmake:	QT += core
继承():	QObject

enumerated type

thread priority

enum Priority {
    
     IdlePriority, LowestPriority, LowPriority, NormalPriority, HighPriority,, InheritPriority }

{ idle priority, lowest priority, low priority, normal priority, high priority, ..., inherit priority }

This enumerated type indicates how the operating system should schedule newly created threads.

constant value describe
QThread::IdlePriority 0 Only dispatched when no other threads are running.
QThread::LowestPriority 1 Scheduling frequency is lower than low priority.
QThread::LowPriority 2 Scheduling frequency is lower than normal priority.
QThread::NormalPriority 3 The default priority of the operating system.
QThread::HighPriority 4 Scheduled more frequently than normal priority.
QThread::HighestPriority 5 Scheduled more frequently than high priority.
QThread::TimeCriticalPriority 6 Schedule as often as possible.
QThread::InheritPriority 7 Use the same priority as the creating thread. It's the default value.

member function

type method illustrate
Constructor QThread(QObject *parent = nullptr) Parameter parent class QObject pointer
virtual ~QThread() Virtual destructor, when the base class pointer points to a subclass, when using delete, the subclass destructor will be called first, and then the parent class constructor will be called to release resources.
QAbstractEventDispatcher * eventDispatcher() const
void exit(int returnCode = 0)
bool isFinished() const
bool isInterruptionRequested() const
bool isRunning() const
int loopLevel() const
QThread::Priority priority() const
void requestInterruption()
void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
void setPriority(QThread::Priority priority)
void setStackSize(uint stackSize)
uint stackSize() const
bool wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever)) Blocks a thread until any of the following conditions are met, which provides similar functionality to the POSIX pthread_join() function.
bool wait(unsigned long time)

overridable function

virtual bool	event(QEvent *event) override

public slot

What is a public slot function that can be directly called by subclasses

void	quit()
void	start(QThread::Priority priority = InheritPriority)
void	terminate()

Signal

void	finished()
void	started()

static member function

QThread *	create(Function &&f, Args &&... args)
QThread *	create(Function &&f)
QThread *	currentThread()
Qt::HANDLE	currentThreadId()
int		idealThreadCount()
void	msleep(unsigned long msecs)
void	sleep(unsigned long secs)
void	usleep(unsigned long usecs) //强制当前线程休眠微秒。
//[将当前线程的执行让给另一个可运行线程(如果有)。请注意,操作系统决定切换到哪个线程。]
void	yieldCurrentThread()

protection function

int	exec()
virtual void	run()

static protection function

Enables or disables termination of the current thread based on the enabled parameter. The thread must be started by QThread.

void	setTerminationEnabled(bool enabled = true)

QThread simple case 1

Official example, trustworthy
For example: Worker is a child thread we created.
Inherit the advantages of QObject: safe memory recovery, support for signals and slots.

For example: Controller is the main thread.

Common ground: they all inherit from QObject

I recommend this way of writing connect in the code. It doesn’t matter how the parameters are changed, reducing the number of modifications.

The characteristics of this kind of thread : each slot function in the task thread is an event loop, that is, you can handle time-consuming operations, read and write files, data calculation, a large number of loops, etc. good).

class Worker : public QObject
{
    
    
    Q_OBJECT

public slots:
    void doWork(const QString &parameter) {
    
    
        QString result;
        /* ... 处理大数据 ... */
        emit resultReady(result); //处理完数据,发到主线程显示
    }

signals:
    void resultReady(const QString &result);
};

class Controller : public QObject
{
    
    
    Q_OBJECT
    QThread workerThread;//线程栈 自动销毁,推荐使用
public:
    Controller() {
    
    
        Worker *worker = new Worker; //创建任务子线程
        worker->moveToThread(&workerThread);	//添加到线程,实际应该可以添加多个任务子线程。
        
        connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);//线程完成这个任务,就将这个任务线程对象删除
        
        connect(this, &Controller::operate, worker, &Worker::doWork);
        //发射信号,通知任务线程做事。
        
        connect(worker, &Worker::resultReady, this, &Controller::handleResults);//接收任务子线程处理好的数据
        
        workerThread.start(); //正式开启线程,
    }
    ~Controller() {
    
    
        workerThread.quit();	//先退出没处理的任务
        workerThread.wait();	//已经在处理的任务,等待处理完,在退出
    }
public slots:
    void handleResults(const QString &);
signals:
    void operate(const QString &);
};

The code in the task slot will be executed in a separate thread. However, you are free to connect the task thread's slot to any signal from any object, from any thread. Due to a mechanism called queuing connections , 跨不同线程连接信号和插槽是安全的.

QThread simple case 2

Another way to have your code run in a separate thread is to subclass QThread and reimplement run(). This kind of use scenario generally does not need to interact with the main thread, such as only completing file writing operations and so on.
For example:

//任务线程
class WorkerThread : public QThread
{
    
    
    Q_OBJECT
    void run() override {
    
    
        QString result;
        /* ... here is the expensive or blocking operation ... */
        emit resultReady(result);
    }
signals:
    void resultReady(const QString &s);
};
//主线程 分配任务
void MyObject::startWorkInAThread()
{
    
    
    WorkerThread *workerThread = new WorkerThread(this);//传入this,就是QObject的指针,资源的释放,即是线程的构造函数传参。
    
    connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
    
    connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
    
    workerThread->start();//开启run()方法
}

In this example, the thread will runexit after the function returns. Unless called exec(), no event loop will run in the thread (that is, after this thing is done, the event loop will no longer be executed).


It's important to remember that a QThread instance exists in the old thread that instantiates it, not in the new thread that calls run(). This means that all QThread's queue slots and methods called will be executed in the old thread. Therefore, developers wishing to call slots in new threads must use the work object methods; new slots should not be implemented directly in subclassed QThread.


Unlike queuing slots or calling methods, methods called directly on a QThread object will execute in the thread that called the method. When subclassing QThread, remember that the constructor is executed in the old thread (with the same main thread id), and run() is executed in the new thread (with the new thread id). If a member variable is accessed from two functions, the variable is accessed from two different threads. Check to see if it is safe to do so.


Note : Care must be taken when interacting with objects across different threads. In general, functions can only be called from the thread that created the QThread object itself (such as setPriority()), unless otherwise stated in the documentation.

Guess you like

Origin blog.csdn.net/m0_45463480/article/details/130905992