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 未完待续

相关推荐
xcyxiner8 小时前
DicomViewer (添加模型类)3
qt
xcyxiner1 天前
DicomViewer (目录调整) 2
qt
xcyxiner1 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
桥田智能3 天前
桥田智能 QT-650S:面向白车身焊装的 800kg 重载快换解决方案
开发语言·qt·系统架构
森G3 天前
75、服务器源码解析---------云视频服务项目
linux·服务器·网络·c++·qt
森G3 天前
77、线程池原理和实现------服务器源码解析----云视频服务项目
服务器·c++·qt
森G3 天前
71、打包发布---------打包发布
c++·qt
初圣魔门首席弟子3 天前
Node.js 详细介绍(知识库版)
windows·qt·node.js·知识库
C++ 老炮儿的技术栈3 天前
Qt工控实战:自研机器人TCP长连接客户端(粘包处理+心跳保活+自动重连完整源码解析)
qt·tcp/ip·机器人