QConcurrent::run 的 QMutex 没有按预期工作?

QMutex with QConcurrent::run not working as expected?

我正在制作一个 Qt GUI 应用程序,它使用自定义 QLabel class(名称为 ImageInteraction)来显示来自流式摄像机的图像,同时还允许在图像上进行鼠标交互.由于 GUI 具有其他功能,自定义的 QLabel class 完成了从相机中提取图像并通过 while 循环更新其显示图像的工作,该循环在另一个函数中为 运行线。代码如下:

void ImageInteraction::startVideo()
{
    if (!capture.open(streamUrl))
    {
        QMessageBox::warning(this, "Error", "No input device availabe!");
    }
    else
    {
        QFuture<void> multiprocess = QtConcurrent::run(this, &ImageInteraction::loadVideo);
    }
}

void ImageInteraction::loadVideo()
{
    while(loopContinue){
    cv::Mat frame;
    capture.read(frame);
    if(!frame.empty())
    {
        cv::cvtColor(frame, frame, CV_BGR2RGBA);
        cv::resize(frame, frame, cv::Size(this->width(), this->height()), 0, 0);
        QImage image(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGBA8888);
                this->setPixmap(QPixmap::fromImage(image));
            }
    }
    capture.release();
 }

这里capturecv::VideoCapture类型,loopContinue是boolean类型,初始设置为true。有一个 closeEvent() 函数调用停止从相机捕获图像的方法。

void MainWindow::closeEvent(QCloseEvent *event)
{
    liveVideo->stopVideoThread();//liveVideo is a pointer to an object of ImageInteraction
    event->accept();
}

其中 stopVideoThread 只是将布尔标志 loopContinue 设置为 false 并具有以下简单代码:

void ImageInteraction::stopVideoThread()
{
    mutex.lock();//QMutex mutex;
    loopContinue = false;
    mutex.unlock();
}

根据我的理解,一旦 stopVideoThread 方法被调用并且 loopContinue 设置为 false,loadVideo 方法中的 while 循环应该停止。但实际上,当按下关闭按钮时,显然它不会停止 while 循环并且应用程序崩溃并显示一条消息:

The inferior stopped because it received a signal from the operating system.

Signal name : SIGSEGV
Signal meaning : Segmentation fault

我是否错误地使用了 QtConcurrent::run 方法和 QMutex 对象?你能确定是什么问题吗?仅供参考,OS 是 ubuntu 14.04,IDE 是 QtCreator。

谢谢!

以下只是对上述评论中提到的改进的想法。

class ImageInteraction
{
public:
    ~ImageInteraction()
    {
        multiprocess_.waitForFinished();
    }

    void startVideo()
    {
        if (!capture.open(streamUrl))
        {
            QMessageBox::warning(this, "Error", "No input device availabe!");
        }
        else
        {
            multiprocess_ = QtConcurrent::run(this, &ImageInteraction::loadVideo);
        }
    }

    void loadVideo()
    {
        while(loopContinue_)
        {
            cv::Mat frame;
            capture.read(frame);
            if(!frame.empty())
            {
                cv::cvtColor(frame, frame, CV_BGR2RGBA);
                cv::resize(frame, frame, cv::Size(this->width(), this->height()), 0, 0);
                QImage image(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGBA8888);
                this->setPixmap(QPixmap::fromImage(image));
            }
        }
        capture.release();
    }

    void stopVideoThread()
    {
        loopContinue_ = false;
        //multiprocess_.waitForFinished(); // you can call this here if you want to make sure that the thread has finished before returning
    }

private:
    QFuture<void> multiprocess_;
    std::atomic<bool> loopContinue_;
};