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可以退出