tbb concurrent_bounded_queue多个线程访问

时间:2016-10-25 03:44:21

标签: c++ multithreading qt tbb

我有以下代码:

tbb::concurrent_bounded_queue<Image> camera_queue_;
camera_queue_.set_capacity(1);

struct Image
{
    int hour_;
    int minute_;
    int second_;
    int msec_;
    QImage image_;

    Image(){hour_ = -1; minute_ = -1; second_ = -1; msec_ = -1; image_ = QImage();}
    Image& operator=(Image const& copy)
    {
        this->hour_ = copy.hour_;
        this->minute_ = copy.minute_;
        this->second_ = copy.second_;
        this->msec_ = copy.msec_;
        this->image_ = copy.image_;
        return *this;
    }
};

在Qt线程中:

的ThreadA:

tbb::concurrent_bounded_queue<Image> image_queue_;
image_queue_.set_capacity(1);
Image cur_image_;
void Worker::process() {

    while(1)
    {

        if(quit_)
            break;

        {
            camera_queue_.pop(cur_image_);
            image_queue_.push(cur_image_);
        }

        emit imageReady();
    }

    emit finished();
}

Image Worker::getCurrentImage()
{
    Image tmp_image;
    image_queue_.pop(tmp_image);
    return tmp_image;
}

在另一个主题中:

ThreadB:

Producer::Producer(){
    work_ = new Worker();
    work_->moveToThread(workerThread_);
    QObject::connect(workerThread_, &QThread::finished, work_, &QObject::deleteLater);
    QObject::connect(this, &Producer::operate, work_, &Worker::process);
    QObject::connect(work_, &Worker::imageReady, this, &Producer::displayImage);
    QObject::connect(this, &Producer::stopDecode, work_, &Worker::stop);
    workerThread_->start();
    emit operate();
}

void Producer::process() {

    while(1)
    {

        if(quit_)
            break;

        {
            camera_queue_.push(GetImage());
        }

    }

}


void Producer::displayImage()
{
    Image tmp = std::move(work_->getCurrentImage());
    widget_->showImage(tmp.image_);
}

但是,在主线程中,我有一个功能,使用户可以单击按钮来获取当前图像:

bool Producer::SaveImage()
{

    Image img = std::move(work_->getCurrentImage());
    std::string fileName = std::to_string(img.hour_) + "-" + std::to_string(img.minute_) + "-" + std::to_string(img.second_) + "-" + std::to_string(img.msec_/1000) + ".jpg";
    std::string outFileName = folder + "/" + fileName;

    return img.image_.save(QString::fromStdString(outFileName));
}

问题是:

当用户未单击按钮调用Producer :: SaveImage()时,图像解码和显示会顺利运行。但是当用户调用Producer :: SaveImage()时,整个程序都会卡住(卡顿现象?)。 GUI响应变得不那么顺利。用户调用SaveImage越多,GUI响应就越慢。

任何人都可以帮忙解释原因吗?有没有办法解决这个问题?

1 个答案:

答案 0 :(得分:0)

为什么要使用并发队列?看起来有一个同步机制,你主要依赖它,而不是像class D extends A with C with B { override def print(): Unit = super.print() } 那样使用concurrent_queue进行同步和通信。

问题是,当您设置capacity = 1时,concurrent_bounded_queue的两个操作都将阻塞,直到队列中有足够的项目空间。例如。如果队列中已包含项目,则push操作将被阻止。而且,由于您使用其他通知机制控制线程,因此可能会遇到死锁。

特别是,尝试交换下面的操作:

    camera_queue_.pop(cur_image_);
    emit imageReady();
    image_queue_.push(cur_image_);

这应该准备接收图像的线程(如果我理解正确的话)并且它将阻塞其image_queue_.pop()方法,那么这个线程将放置新图像并解锁收件人。可能存在与此类似的其他问题,因此,请重新考虑所有同步。