在一个 Qt6.5.3 的项目中,有一个 ImageProcessor
类负责在子线程中进行图像处理,并有一个 MainWindow
类在主线程中进行界面更新。虽然 ImageProcessor::processingDone
信号被成功触发,但 MainWindow::updateScene
槽函数却没有被调用。这里详细描述一下涉及的代码和逻辑。
该类在一个独立的线程中运行,并负责图像处理。当图像处理完成后,它会发出一个 processingDone
信号。
class ImageProcessor : public QObject
{
Q_OBJECT
public:
// ... 构造函数和其他成员函数
signals:
void processingDone(QVector<DetectResult> detectResult);
public slots:
void processImage()
{
// ... 图像处理逻辑
emit processingDone(res);
}
void onProcessingDone(const QVector<DetectResult>)
{
processImage();
}
};
// 在构造函数中
ImageProcessor::ImageProcessor(/* ... */)
{
connect(this, &ImageProcessor::processingDone, this, &ImageProcessor::onProcessingDone);
}
该类运行在主线程中,负责接收 ImageProcessor
的 processingDone
信号,并通过 updateScene
槽函数进行处理。
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
// ... 构造函数和其他成员函数
public slots:
void updateScene(QVector<DetectResult> detectResult)
{
// ... 更新界面逻辑
}
};
// 在构造函数中
MainWindow::MainWindow(QWidget* parent)
{
// ... 创建 ImageProcessor 和子线程
QObject::connect(imageProcessor, &ImageProcessor::processingDone, this, &MainWindow::updateScene);
}
在 ImageProcessor
类中,processingDone
信号和 onProcessingDone
槽函数被连接了起来,而 onProcessingDone
函数内部又调用了 processImage
,这导致了无限递归。
void ImageProcessor::onProcessingDone(const QVector<DetectResult>)
{
processImage();
}
由于这种递归持续发生在子线程中,它占据了所有可用的事件循环时间,因此 MainWindow::updateScene
没有机会被执行。
修改 ImageProcessor
类的构造函数,使用 Qt::QueuedConnection
来连接 processingDone
和 onProcessingDone
。
ImageProcessor::ImageProcessor(/* ... */)
{
connect(this, &ImageProcessor::processingDone, this, &ImageProcessor::onProcessingDone, Qt::QueuedConnection);
}
这样,onProcessingDone
将在下一个事件循环周期中被调用,给其他等待的槽函数(如 MainWindow::updateScene
)提供了执行的机会。
在 Qt 的多线程环境中使用信号和槽时,需要特别小心潜在的递归和事件循环阻塞问题。正确地设置信号和槽的连接类型和执行顺序是避免这类问题的关键。希望本文能为您提供有用的信息和解决方案。