队列"/>
Qt C++子线程中执行任务队列
概述
在项目中经常会遇到这种情况,当要执行一些耗时操作的时候,如果是在主线程中进行,将会导致界面阻塞,整体体验就会很差,那么,这种情况通常会将任务扔到子线程中去执行。那如果说需要执行的这些任务很多,这时候就需要将任务放到一个队列中,然后循环在子线程中执行任务。所以,这里来介绍一下该场景的框架设计,如何在子线程中执行耗时任务队列。
示例
上面的描述可能不是很好理解,接下来看一个实际的用例。
假如,我们要保存很多高清图片到本地,由于保存动作是比较耗时的,然后由于数量较多,我们将需要保存的任务封装起来交给线程中去一个个执行。所以接下来看看代码的设计:
首先创建一个任务类,用于管理该任务的所有信息:
// 单个任务类
class Task
{
public:Task(QImage image,QString path);bool saveImage();QString path();
private:QImage m_image; //将要保存的图片QString m_strSavePath; //保存地址
};
Task::Task(QImage image, QString path):m_image(image),m_strSavePath(path)
{
}bool Task::saveImage()
{bool ret = false;if(!m_image.isNull() && !m_strSavePath.isEmpty()){ret = m_image.save(m_strSavePath);}return ret;
}QString Task::path()
{return m_strSavePath;
}
然后创建线程 用于执行任务列表:
class ImageSaveCore : public QThread
{Q_OBJECT
public:ImageSaveCore(QObject * parent = nullptr);void run();void addTask(Task * task); //添加任务,在最前面添加,保证最后添加的优先级最高Task * popTask();void stop(){m_bStart = false;}signals:void sigImgSaveFinish(QString path); //图片保存完成
private:QList<Task *> m_taskList; //任务列表QMutex m_mutex;bool m_bStart = true;
};
ImageSaveCore::ImageSaveCore(QObject * parent):QThread (parent)
{
}void ImageSaveCore::run()
{while (m_bStart) {Task * task = popTask();if(task){if(task->saveImage()){emit sigImgSaveFinish(task->path());delete task;task = nullptr;}}msleep(10);}
}void ImageSaveCore::addTask(Task *task)
{m_mutex.lock();m_taskList.push_front(task);m_mutex.unlock();
}Task *ImageSaveCore::popTask()
{m_mutex.lock();Task * task;if(m_taskList.size() == 0){task = nullptr;}else{task = m_taskList.takeFirst();}m_mutex.unlock();return task;
}
可以看到,添加任务直接调用addTask,将封装好的任务添加到列表中去,然后在 run中会一直循环执行任务队列。只要有任务进来就会自动执行,并且在执行完后会自动删除任务。
然后再看如何调用:
m_pSaveCore = new ImageSaveCore(this);m_pSaveCore->start();/*...*/ m_pSaveCore->addTask(new Task(image,"xxx"));
这里为了方便,就只列出了添加任务的方式,其中 image 就是内存中需要保存到本地的图片,xxx 就是要保存的完整路径(包含文件名)。最后析构的时候记得关闭线程。就不多介绍了。
OK, 以上的结构就是介绍如何在线程中执行这种任务队列,不影响主线程的执行,其实这种方式在项目中使用得挺多,可以直接根据该结构去进行扩展即可。
更多推荐
Qt C++子线程中执行任务队列
发布评论