DicomViewer (后台线程处理文件)4

1 背景

上一篇初始化了模型类和控制器,这一篇在最开始菜单读取文件的基础上继续处理。 先把读取的文件路径放到后台线程,再挨个处理文件。

2正文

2.1 FilesImporter 后台线程处理

FilesImporter.h文件添加如下

c++ 复制代码
public:
  void startImporter();
  void stopImporter();
  void addFiles(const QStringList& t_paths);
  void importFiles();

protected:
  void run() override;
  
private:
  QMutex m_filesMutex;
  bool m_isWorking = false;
  std::deque<QString> m_filesPaths;
  std::unique_ptr<CoreController> m_coreController;
  • 先调用startImporter
  • 结束的时候调用stopImporter
  • 菜单选择文件后调用addFiles,m_filesMutex提供互斥锁,m_filesPaths提供队列存放文件路径
  • importFiles 在run循环解析的时候处理,m_coreController提供文件处理的方法
  • run 重写

2.2 选择文件调用上面的处理

2.2.1 GUICenter.h 初始化上面的类,并调用添加addFiles

arduino 复制代码
  ~GUICenter();

signals:
  void addFiles(const QStringList& t_paths);

private:
  std::unique_ptr<FilesImporter> m_fileImporter;
};

2.2.2 GUICenter.cpp

c++ 复制代码
GUICenter::GUICenter(QWidget* parent)
    : QWidget(parent)
{
  m_fileImporter = std::make_unique<FilesImporter>(this);
  m_fileImporter->startImporter();
  connect(this,
          &GUICenter::addFiles,
          m_fileImporter.get(),
          &FilesImporter::addFiles);
}

GUICenter::~GUICenter()
{
  m_fileImporter->stopImporter();
}

void GUICenter::onOpenFile()
{
  QFileDialog fileDialog(this, "选择文件");
  fileDialog.setFileMode(QFileDialog::ExistingFile);
  if (fileDialog.exec() == QDialog::Accepted) {
    emit this->addFiles(fileDialog.selectedFiles());
  }
}

因为FilesImporter 是线程,这里使用信号槽来调用addFiles,初始化的时候将信号跟FilesImporter的slot(addFiles)绑定,选择文件后,直接触发信号。

析构函数也添加上,可以调用之前的stopImporter。

2.3 FilesImporter 后台线程处理2

在2.1只添加了头,这里将后续的定义也补充上

2.3.1 FilesImporter.cpp 处理

c++ 复制代码
FilesImporter::FilesImporter(QObject* parent)
    : QThread(Q_NULLPTR)
{
}

void FilesImporter::startImporter()
{
  m_isWorking = true;
  start();
}

void FilesImporter::stopImporter()
{
  if (!m_isWorking) {
    return;
  }
  m_isWorking = false;
  quit();
  wait();
  m_filesPaths.clear();
}

void FilesImporter::run()
{
  while (m_isWorking) {
    importFiles();
  }
}

void FilesImporter::addFiles(const QStringList& t_paths)
{
  std::lock_guard<QMutex> lock(m_filesMutex);
  for (const auto& path : t_paths) {
    m_filesPaths.push_back(path);
  }
}

void FilesImporter::importFiles() {}
  • startImporter 开启线程,更新标记在运行中
  • stopImporter 结束线程,清空队列
  • run 如果是在运行中,则执行导入
  • addFiles 先获取锁,再执行添加
  • importFiles 获取锁,循环解析

2.4 编译运行

运行以后选择文件还能关闭窗口,暂时看不出来问题,但是不确定是否有用,所以要调试一下。之前nvim装的dap codelldb 没法在多线程下打断点,这里使用gdb的来打断点调试

2.5 gdb调试

2.5.1 输入gdb 可执行程序

之前编译类库都是debug的,这里编译也是Debug,就直接调试了

bash 复制代码
gdb ./build/DicomViewer

2.5.2 list可以看到有源码

2.5.3 先在FilesImporter::addFiles 打个断点

arduino 复制代码
break FilesImporter::addFiles

2.5.4 执行run

arduino 复制代码
run

第一次会下载,等结束后,选择res下的CT_small.dcm,点击open后会停止打断点的位置

objectivec 复制代码
res/
├── CT_small.dcm
├── ExplVR_LitEndNoMeta.dcm
├── JPEG-LL.dcm
├── JPEG2000.dcm
└── MR_small.dcm

这个点击open后停到断点位置的效果图

2.5.5 单步调试

用list可以查看附近的源码

用step是单步,next是一行

从上面可以看到这里有刚才选择的文件的值

继续等循环结束的时候,查看队列也是有值的,这样说明前面的是没啥问题

2.5.6 结束或者退出

可以选择continue继续运行

关闭可执行程序的就能退出了,然后gdb窗口 输入exit可以退出

2.6 上面的没啥问题,先提交一次

github commit 将选择的文件名存入队列

3 未完待续

相关推荐
杜子不疼.11 小时前
【Qt初识】信号槽(三):机制意义、断开连接与 Lambda 表达式
开发语言·数据库·qt
杜子不疼.14 小时前
【Qt初识】信号槽(二):自定义信号函数与槽函数
开发语言·qt
秋田君14 小时前
Qt_QVariant
开发语言·qt
杜子不疼.14 小时前
【Qt初识】工程起步:项目创建、代码解读与对象树
数据库·c++·qt
安东尼肉店18 小时前
QT 自定义随机验证码校验
开发语言·qt
小徐不徐说2 天前
Qt 线程迁移机制完整实战指南(moveToThread)
开发语言·c++·qt·程序设计
Traveler飞2 天前
Ubuntu20.04 VMware 黑屏无法进入桌面,Ctrl+Alt+F2 可以进入终端,最终发现是磁盘空间满了
qt·ubuntu
m0_587098993 天前
Qt,二进制文件读写建议
开发语言·qt
秋田君3 天前
QT_QT信号与槽机制
开发语言·数据库·qt
辞旧 lekkk3 天前
【Qt】 系统相关:事件与定时器
开发语言·qt·学习·萌新