嵌套的QFuture - QtConcurrent问题

时间:2016-05-18 10:23:43

标签: multithreading qt qtconcurrent qfuture

我遇到这种情况:我需要不断更新某些UI标签,其中包含我从某些SPI传感器读取的值,而不会阻止UI。每个传感器的代码几乎相同,如下所示:

double SPIHandler::scaleGetQuickWeight(){
    double weightValue = SCALE_ERROR_VALUE;

    QElapsedTimer *timer = new QElapsedTimer();
    timer->start();
    QFuture<double> future = QtConcurrent::run(&SPIHandler::thread_scaleGetWeight);
    while(timer->elapsed() < 5000){
        if (future.isFinished()){
            future.end();
            weightValue = future.result();
            return weightValue;
        }
    }
    //when called by the functions I posted below, the program always ends here
    future.cancel();
    myParent->log("Malfunctioning scale", MainWindow::LOG_ERROR);
    return SCALE_ERROR_VALUE;
}

double SPIHandler::thread_scaleGetWeight(){
    float val;  
    //myParent->log("check");
    if (scale_read_value(fd_scale, &val) == 0){
        return ftod(convertReadingsIntoWeight(val, k_cal, q_cal)*1000);
    } else {
        myParent->log("Malfunctioning scale in QtConcurrent", MainWindow::LOG_ERROR);
        return SCALE_ERROR_VALUE;
    }

}

对于每个传感器,我有一个由QtConcurrent :: run()调用启动的线程,如果在5秒后它没有给出结果,我会停止:代码的这些部分在其他地方使用时效果很好。 当我尝试从另一个线程调用包含QtConcurrent :: run()调用的函数时出现问题,而该调用又是由QTimer超时启动的另一个QtConcurrent :: run()创建的。 QWidget中需要更新标签的相关代码是:

DiagnosticWindow::DiagnosticWindow(QWidget *parent) :
    QTabWidget(parent),
    ui(new Ui::DiagnosticWindow)
{
    [...]    
    //connect to make sure that timer is running only when the right tab is selected
    connect(this, SIGNAL(currentChanged(int)), this, SLOT(on_diagnosticWindow_currentChanged(int)));
    //setting up timer
    timer = new QTimer();
    connect(timer, SIGNAL(timeout()), this, SLOT(on_timer_timeout()));
    ///setting up QFutureWatcher
    watcher = new QFutureWatcher<void>();
    connect(watcher, SIGNAL(finished()), this, SLOT(updateGraphics()));
    [...]
}

void DiagnosticWindow::on_diagnosticWindow_currentChanged(int index)
{
    //slot to start timer when tab 2 is selected
    if (index == 2){    
        [...]
        timer->setSingleShot(false);
        timer->start(750);
    } else{
        printf("timer stopped\r\n");
        timer->stop();
        [...]
    }
}

void DiagnosticWindow::on_timer_timeout(){
    //slot to start QtConcurrent on timer timeout
    QFuture<void> future = QtConcurrent::run(&diagnosticWindow::updateValues);
    watcher->setFuture(future);
}

void DiagnosticWindow::updateValues(){
    //function run by QFuture: I didn't post the code of these functions, 
    //but each one simply calls the respective function written like the one
    //posted above
    weight = myParent->deviceScaleGetQuickWeight();
    temperature = myParent->devicePressGetValue();
    pressure = myParent->deviceTempGetValue();
}

void DiagnosticWindow::updateGraphics(){
    //slot called when QFutureWatcher signals isFinished()
    ui->lbl_peso->setText(QString("%1").arg(weight));
    ui->lbl_pressione->setText(QString("%1").arg(pressure));
    ui->lbl_temperatura->setText(QString("%1").arg(temperature));
}

总而言之,这应该是行为:

  选择

标签 - &gt;计时器开始 - &gt;计时器停止 - &gt; QFuture 1开始   然后调用另一个QFuture 2 - &gt; QFuture 2结束 - &gt; QFuture 1   结束 - &gt;用户界面更新

它确实以这种方式工作,但它总是给我带来故障错误。 QFuture 1正在工作,因为在5秒后,我收到了故障错误,所以在我看来,QFuture 2从不调用该功能。我尝试添加评论&#34; myParent-&gt;日志(&#34; check&#34;);&#34;到QFuture 2调用的函数有证明该函数被调用,但在这种情况下我从来没有得到那条日志消息(但是当我从代码的其他部分读取传感器时我得到它)。

问题是:上面代码中的某些内容可以解释这种行为吗?有什么我想念的吗?如果需要,我可以添加更多代码,但由于我可以正确读取传感器值,即使是来自同一个DiagnosticWindow类,我也不认为它可以提供帮助。 谢谢你们

0 个答案:

没有答案