添加到QQueue崩溃程序

时间:2019-04-03 17:27:37

标签: c++ qt queue thread-safety mandelbrot

我正在尝试在QT中绘制Mandelbrot集。一切都完成了,看起来不错,但是需要一些时间来计算像素的颜色,所以我想将图片分割成4个,然后对分离的线程进行计算。 线程正在工作,问题是:数学运算后,我想生成对象(我的Pixel结构),并使用enqueue()方法将其传递给queque,该方法从我的paintEvent中获取x,y和color进行绘制。 添加到队列中将生成:

18:09:15: The program has unexpectedly finished.
18:09:15: The process was ended forcefully.

没有它,线程正常工作

Plot.cpp中的方法Plot :: get_iterations_from_thread()

#include "plot.h"


QMutex Plot::mutex;

Plot::Plot(QWidget *parent) : QWidget(parent)
{ 
    connect(this,
            SIGNAL(get_iterations(unsigned int, unsigned int, int, int)),
            this,
            SLOT(get_iterations_from_thread(unsigned int, unsigned int, int, int)),
            Qt::ConnectionType::QueuedConnection);

    th1.set_values(0, (width/2)-1,
                   0, (height/2)-1,
                   cxmin, cxmax, cymin, cymax,
                   max_check, "TH1");
    std::cout << th1.name + " values setted" << std::endl;

    th2.set_values((width/2)+1, width,
                   0, (height/2)-1,
                   cxmin, cxmax, cymin, cymax,
                   max_check, "TH2");
    std::cout << th2.name + " values setted" << std::endl;

    th3.set_values(0, (width/2)-1,
                   (height/2)+1, height,
                   cxmin, cxmax, cymin, cymax,
                   max_check, "TH3");
    std::cout << th3.name + " values setted" << std::endl;

    th4.set_values((width/2)+1, width,
                   (height/2)+1, height,
                   cxmin, cxmax, cymin, cymax,
                   max_check, "TH4");
    std::cout << th4.name + " values setted" << std::endl;

    th1.start();
    th2.start();
    th3.start();
    th4.start();
}

void Plot::get_iterations_from_thread(unsigned int iterations, unsigned int max_check, int x,  int y)
{
    mutex.lock();
    std::cout << "generating pixel" << std::endl;
    Pixel pix(x, y, iterations, max_check);
    pixels.enqueue(pix);
    std::cout << "pixel generated!" << std::endl;
    mutex.unlock();
}

void Plot::paintEvent(QPaintEvent *e)
{
    std::cout << "paintEvent" << std::endl;
    mutex.lock();
    QPainter painter;
    painter.begin(this);
    QPen pen(Qt::white);
    pen.setWidth(1);
    pen.setCapStyle(Qt::SquareCap);
    if(!pixels.isEmpty()){
        foreach(Pixel pixel, pixels){
            std::cout << "painting " + std::to_string(pixel.get_x()) + "," + std::to_string(pixel.get_y()) << std::endl;
            pen.setColor(pixel.get_color());
            painter.setPen(pen);
            painter.drawPoint(pixel.get_x(), pixel.get_y());
            pixels.dequeue();
        }
    }
    painter.end();

    mutex.unlock();

}

使用它:

void CountingThread::run()
{
    Plot * window = dynamic_cast<Plot*>(parent());
    for(int x=x_start; x<x_stop; ++x){
        for(int y=y_start; y<y_stop; ++y){

            std::complex<double> c(cxmin + x/(width-1.5)*(cxmax-cxmin), cymin + y/(height-0.5)*(cymax-cymin));
            std::complex<double> z(0,0);
            unsigned int iterations;
            for (iterations = 0; iterations < max_check && std::abs(z) < 2.0; ++iterations) {
                z = z*z + c;
            }

            std::cout << name + " done for: " + std::to_string(x) + "," + std::to_string(y) + " " << std::endl;
            //emit(window->get_iterations(iterations, max_check, x, y));
            window->get_iterations_from_thread(iterations, max_check, x, y);
            std::cout << name + " emitted" << std::endl;
        }
    }

}

和情节.h

#ifndef PLOT_H
#define PLOT_H

#include <QWidget>
#include <QPainter>

#include <iostream>

#include "countingthread.h"
#include "pixel.h"

class Plot : public QWidget
{
    Q_OBJECT
public:
    explicit Plot(QWidget *parent = nullptr);
    static QMutex mutex;
    QQueue<Pixel> pixels;

private:
    void Plot::paintEvent(QPaintEvent *e) override;
    CountingThread th1;
    CountingThread th2;
    CountingThread th3;
    CountingThread th4;

    int width = 820;
    int height = 640;
    double cxmin = -1.5;
    double cxmax = 0.5;
    double cymin = -1.0;
    double cymax = 1.0;
    unsigned int max_check = 100;

signals:
    void get_iterations(unsigned int iterations, unsigned int max_check, int x,  int y);

public slots:
    void get_iterations_from_thread(unsigned int iterations, unsigned int max_check, int x,  int y);
};

#endif // PLOT_H

顺便说一句:对emit函数进行注释是因为它不起作用,我也不知道为什么,这使我非常沮丧

0 个答案:

没有答案