QThread
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 ¶meter) {
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
run
exit after the function returns. Unless calledexec()
, 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.