如何解决多线程绘图不流畅的问题?

时间:2019-05-16 02:50:36

标签: c++ multithreading qt qthread

我用Qt编写了一个数据采集程序。我使用QSemphore编写的双缓存区域的子线程收集数据。

void QThreadShow::run() {
    m_stop=false; // when start thread,m_stop=false

    int n=fullBufs.available();
    if (n>0)
        fullBufs.acquire(n); 

    while (!m_stop) {
        fullBufs.acquire(); // wait fo full buffer
        QVector<double> dataPackage(BufferSize); 
        double seq=bufNo;
        if (curBuf==1) 
            for (int i=0;i<BufferSize;i++){
                dataPackage[i]=buffer2[i]; // copy data from  full buffer
            } 
        else
            for (int i=0;i<BufferSize;i++){
                dataPackage[i]=buffer1[i];
            }

        for (int k=0;k<BufferSize;k++) {
            vectorQpointFbufferData[k]=QPointF(x,dataPackage[k]);
        }
        emptyBufs.release(); // release a buffer
        QVariant variantBufferData;  
        variantBufferData.setValue(vectorQpointFbufferData);
        emit newValue(variantBufferData,seq); // send data to main thread
    }
    quit();
}

当子线程的缓存收集了500个数据时,数据将输入到QVector中并发送到主线程,并每隔20ms直接分配给qchartview中的线系列以进行绘制。我使用QtChart绘制数据图表。

void MainWindow::onthreadB_newValue(QVariant bufferData, double bufNo) {
    // Analysis of QVariant data
    CH1.hardSoftDataPointPackage = bufferData.value<QVector<QPointF>>();
    if (ui->CH1_Source->currentIndex()==0) {
        for (int p = 0;p<CH1.hardSoftDataPointPackage.size();p++) {
            series_CH3->append(CH1.hardSoftDataPointPackage[p]);
        }        
    }
}

主线程中有一个计时器,间隔为20ms,并且有一个双倍的时间(时间=时间+1),它控制着X轴。

void MainWindow::drawAxis(double time) {
    // dynamic draw x axis
    if (time<100) {
        axisX->setRange(0, TimeBase/(1000/FrameRate) * 10);    
        // FrameRate=50
    } else {
        axisX->setRange(time-TimeBase/(1000/FrameRate) * 10, time);
    }
}

但是,当我运行程序时,存在一个问题,每次子线程将数据发送到主线程时,主线程都会卡住几秒钟,而绘图也会卡住几秒钟。我在主线程中添加了一条曲线,以从主线程获取数据,发现两条曲线将同时卡住。我不知道如何解决这个问题。

此外,我希望主线程在20ms内均匀地从子线程中提取数据,而不是一次绘制所有点。

1 个答案:

答案 0 :(得分:2)

您的主线程卡住了,因为您一次复制(添加到系列中)很多数据。相反,您可以在不发出信号的情况下在线程实例内部收集所有数据。每20毫秒从主线程获取少量收集的数据。

类似这样的东西:

while(!m_stop)
{
   ...
   //QVariant variantBufferData;  
   //variantBufferData.setValue(vectorQpointFbufferData);
   //emit newValue(variantBufferData,seq);//send data to main thread

   //instead this just store in internal buffer
   m_mutex.lock();
   m_internalBuffer.append(vectorQpointFbufferData);
   m_mutex.unlock();
}

读取方法

QVector<QPointF> QThreadShow::takeDataPiece()
{
    int n = 4;
    QVector<QPointF> piece;
    piece.reserve(n);
    m_mutex.lock();
    for (int i = 0; i < n; i++)
    {
         QPointF point = m_internalBuffer.takeFirst();
         piece.append(point);
    }
    m_mutex.unlock();
    return piece;
}

并且在主线程中读取超时插槽

void MainWindow::OnDrawTimer()
{
     QVector<QPointF> piece = m_childThread.takeDataPiece();
     //add to series
     ...
     //drawAxis
     ...
}