Multithreading c++;11在构造函数中初始化线程以执行方法

Multithreading c++;11在构造函数中初始化线程以执行方法,multithreading,qt,c++11,Multithreading,Qt,C++11,我想渲染一个三角形,它的坐标由一个单独的线程不断更新(使用m_偏移)。线程在整个运行时并行运行 我的应用程序使用GL小部件初始化QT窗口 #include "mainwindow.h" #include <QApplication> #include <iostream> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show();

我想渲染一个三角形,它的坐标由一个单独的线程不断更新(使用m_偏移)。线程在整个运行时并行运行

我的应用程序使用GL小部件初始化QT窗口

#include "mainwindow.h"
#include <QApplication>
#include <iostream>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}
#包括“mainwindow.h”
#包括
#包括
int main(int argc,char*argv[])
{
质量保证申请a(argc、argv);
主窗口w;
w、 show();
返回a.exec();
}
GL小部件(glwidget.cpp)的定义如下:

#include "glwidget.h"

#include <iostream>
#include <thread>

GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent)
{

    m_offset = 0.0

    // HERE, I want to start a thread on updateCoordinates().
    // Something like this: (this doesn't work)
    //std::thread mythread (updateCoordinates);   
    // or this (getting segfault)
    //std::thread mythread (&GLWidget::updateCoordinates, this);


}

void GLWidget::initializeGL()
{
    glClearColor(0.2, 0.2, 0.2, 1);
}
void GLWidget::paintGL()
{


    glClear(GL_COLOR_BUFFER_BIT);

    glBegin(GL_TRIANGLES);
        glColor3f(1,0,0);
        glVertex3f(-0.5+m_offset, -0.5+m_offset, 0);
        glColor3f(0,1,0);
        glVertex3f(0.5+m_offset, -0.5+m_offset, 0);
        glColor3f(0,0,1);
        glVertex3f(0.0+m_offset, 0.5+m_offset, 0);
    glEnd();

}
void GLWidget::resizeGL(int w, int h)
{}


void GLWidget::updateCoordinates()
{

    while(true)
    {
        m_offset += 0.0001;
    }

}
#包括“glwidget.h”
#包括
#包括
GLWidget::GLWidget(QWidget*父项):QGLWidget(父项)
{
m_偏移=0.0
//在这里,我想在updateCoordinates()上启动一个线程。
//类似这样的事情:(这不起作用)
//std::线程读取(更新坐标);
//或者这个(错误)
//std::thread mythread(&GLWidget::updateCoordinates,this);
}
void GLWidget::initializeGL()
{
glClearColor(0.2,0.2,0.2,1);
}
void GLWidget::paintGL()
{
glClear(GLU颜色缓冲位);
glBegin(GL_三角形);
gl3f(1,0,0);
glVertex3f(-0.5+m_偏移,-0.5+m_偏移,0);
gl3f(0,1,0);
glVertex3f(0.5+m_偏移,-0.5+m_偏移,0);
gl3f(0,0,1);
glVertex3f(0.0+m_偏移,0.5+m_偏移,0);
格伦德();
}
void GLWidget::resizeGL(int w,int h)
{}
void GLWidget::updateCoordinates()
{
while(true)
{
m_偏移量+=0.0001;
}
}
以下是相应的标题:

#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QGLWidget>

class GLWidget : public QGLWidget
{
    Q_OBJECT
public:
    explicit GLWidget(QWidget *parent = 0);

    void initializeGL();
    void paintGL();
    void resizeGL(int w, int h);

    void startSimulation();
    void stopSimulation();
    void updateCoordinates();

private:
    double m_offset;

signals:

public slots:

};

#endif // GLWIDGET_H
\ifndef GLWIDGET\u H
#定义glu\H
#包括
类GLWidget:publicqglwidget
{
Q_对象
公众:
显式GLWidget(QWidget*parent=0);
void initializeGL();
void paintGL();
无效尺寸(整数w,整数h);
void startSimulation();
void stop模拟();
void updateCoordinates();
私人:
双m_偏移;
信号:
公众时段:
};
#endif//glu\H
如何在该类中跨越一个新线程,该线程在通过
paingll()
更新图形时连续运行
updateCoordinates()


谢谢

您可以使用
QtConcurrent::run
在单独的线程中运行函数

QFuture<void> future = QtConcurrent::run(this,&GLWidget::updateCoordinates );
请注意,
repaint()
信号应连接到连接类型为
Qt::BlockingQueuedConnection
updateGL

在while循环中还应该有一个标志,该标志被选中以终止while和线程

您可以检查由future表示的异步计算的状态,如下所示:

if(future.isRunning())
{
    // It is currently running
}
或者等待它完成:

future1.waitForFinished();
你可以用

虽然存在其他选项,例如QConcurrent,但也有一些选项可以

创建从QObject派生的对象,该对象将负责更新坐标。在每次更新之后,对象可以发出一个带有坐标的信号,然后在主线程上接收回该信号

class Worker : public QObject 
{
    Q_OBJECT

public:
    Worker();
    ~Worker();

public slots:
    void process();

signals:

    typedef QVector<QPoint> PointList;

    void NewCoordinates(PointList points);

private:
    PointList m_pointList;

private:
};


Worker::Worker() {
    // you could copy data from constructor arguments to internal variables here.
}

// --- DESTRUCTOR ---
Worker::~Worker() {
    // free resources
}


// --- PROCESS ---
// Start processing data.
void Worker::process() {

    // calculate new coordinates...

    emit NewCoordinates(m_pointList);
}

要了解如何真正真正地使用QThread,这里有一篇很棒的文章。

感谢您的回复@Nejat。我按照您的建议设置了所有内容:“连接(此、信号(重绘())、此、插槽(paintGL())、Qt::BlockingQueuedConnection);”现在,paintGL()和updateCoordinates()在不同的线程中交替运行。那很好。然而,奇怪的是,三角形图形输出没有得到更新。当我调整窗口大小时,我只能看到三角形移动。你知道为什么会这样吗?@user2926577你应该把信号连接到
QGLWidget::updateGL
updateGL
将调用
paintGL
。我已经更新了答案。谢谢@Nejat,这很有效。我现在遇到的问题是,由于两个线程的执行是交替的(paintGL和updateCoordinates),所以我只能得到60Hz的总体更新率,这与使用线程的目的背道而驰。当我删除
Qt::BlockingQueuedConnection
时,每1000个更新坐标就有一个paintGL,总的更新率为80kHz(kilo!)。但是,现在我无法再使用/单击主窗口中的按钮(沙漏光标)。我如何解决这个问题非常感谢你的建议!当您删除
Qt::BlockingQueuedConnection
时,连接类型将变为
Qt::QueuedConnection
,并且每个发射都会插入一个队列中,该队列的大小会随着时间的推移而增加。可能是因为发射的能量太大了。
class Worker : public QObject 
{
    Q_OBJECT

public:
    Worker();
    ~Worker();

public slots:
    void process();

signals:

    typedef QVector<QPoint> PointList;

    void NewCoordinates(PointList points);

private:
    PointList m_pointList;

private:
};


Worker::Worker() {
    // you could copy data from constructor arguments to internal variables here.
}

// --- DESTRUCTOR ---
Worker::~Worker() {
    // free resources
}


// --- PROCESS ---
// Start processing data.
void Worker::process() {

    // calculate new coordinates...

    emit NewCoordinates(m_pointList);
}
QThread* thread = new QThread;
Worker* worker = new Worker();
worker->moveToThread(thread);

connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
connect(thread, SIGNAL(started()), worker, SLOT(process()));

// tidy up
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

// assuming we're in the MainWindow class, with a NewCoordinates slot function
// collect points - C++ 5 connect syntax
connect(worker, &Worker::NewCoordinates(Worker::PointList), this, &MainWindow::NewCoordinates(Worker::PointList);

// let's go
thread->start();

void MainWindow::NewCoordinates(Worker::PointList pointList)
{
   // handle updated coordinates
}