Nested QFuture - выпуск QtConcurrent

У меня такая ситуация: мне нужно постоянно обновлять некоторые метки интерфейса со значениями, которые я читаю с некоторых датчиков SPI, без блокировки интерфейса. Код практически идентичен для каждого датчика и выглядит так:

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() из другого потока, который, в свою очередь, был создан другим QtConcurrent::run(), запущенным по таймауту QTimer. Соответствующий код в 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));
}

Итак, подведем итог, это должно быть поведение:

вкладка выбирается -> запускается таймер -> останавливается таймер -> запускается QFuture 1 и, в свою очередь, вызывает другой QFuture 2 -> заканчивается QFuture 2 -> заканчивается QFuture 1 -> обновляется пользовательский интерфейс

и это работает таким образом, но это всегда дает мне ошибку сбоя. QFuture 1 работает, потому что через 5 секунд я получаю сообщение о неисправности, поэтому мне кажется, что QFuture 2 никогда не вызывает функцию. Я попытался добавить, что прокомментировал "myParent->log("check");" к функции, вызываемой QFuture 2, чтобы иметь доказательство того, что функция была вызвана, но в этом случае я никогда не получаю это сообщение журнала (но я получаю его, когда читаю с датчика в других частях кода).


Вопрос в том, может ли что-то в приведенном выше коде объяснить такое поведение? Я что-то упускаю? Я могу добавить больше кода, если это необходимо, но, поскольку я могу правильно читать значения датчиков даже из того же класса DiagnosticWindow, я не думаю, что это могло бы помочь. Спасибо, парни

0 ответов

Другие вопросы по тегам