Как решить проблему, что многопоточное рисование не является гладким? - PullRequest
0 голосов
/ 16 мая 2019

Я написал программу сбора данных с 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 и отправляютсяв основной поток и напрямую назначается линейке в qchartview каждые 20 мс для рисования.Я использую 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]);
        }        
    }
}

В главном потоке есть таймер. Интервал составляет 20 мс, и есть двойное время (время = время +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);
    }
}

Но когда я запускаю свою программу, возникает проблема, заключающаяся в том, что каждый раз, когда дополнительная нить отправляет данные в основной поток, основной поток застревает на несколько секунд, а график также застревает на несколько секунд.секунд.Я добавил кривую в основной поток, получая данные из основного потока, и обнаружил, что обе эти кривые будут зависать одновременно.Я не знаю, как решить эту проблему.

Кроме того, я хочу, чтобы основной поток рисовал данные из дочернего потока равномерно в течение 20 мс, а не рисовал все точки одновременно.

1 Ответ

2 голосов
/ 16 мая 2019

Ваш основной поток застрял, потому что вы копируете (добавляете в серию) много данных за один раз. Вместо этого вы можете собрать все свои данные внутри вашего потока, не испуская сигнал. А из основного потока просто берите маленькие кусочки собранных данных каждые 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
     ...
}
...