Многопоточный калькулятор на Qt [закрыт]

138
07 сентября 2019, 10:00

Задача сделать так, чтобы программа работала в двух потоках. Нужно искусственно усыплять поток, дабы эмулировать долгие вычисления.

В первом потоке:

  1. Формируется запрос на вычисление и происходит добавление его в очередь потока 2 (при нажатии на кнопку "=" ).
  2. Вывод результатов (например в qDebug), полученных из потока 2

Во втором (доступ к потоку 2 должен быть потокобезопасным):

  1. Как завершится пред. вычисление, приступать к следующему, поступившему из потока 1.
  2. Извлеченный элемент отправляется на обработку.
  3. Ожидание окончания вычислений
  4. Передача результата в основной поток

С классом QThread не знаком, + читал о нескольких способах реализации, так и не понял как сделать грамотнее.

void MainWindow::equal_pressed()
{
    double displayNumber;
    double secondNum = ui->display->text().toDouble();
    QString DisplayText;
    if (ui->pushButton_add->isChecked())
    {
        qDebug() << "New request: " << firstNum << " + " << secondNum;
        std::thread thread_2([&displayNumber,secondNum,this(){
            displayNumber = compute(add,firstNum,secondNum); 
        });
        thread_2.join();                                        
        // это конечно неправильно, выходит тоже самое что и в одном потоке. Где-то нужно создать std::queue мб и туда помещать запросы
        DisplayText = QString::number(displayNumber,'g',15); // только как.
        ui->display->setText(DisplayText);
        ui->pushButton_add->setChecked(false);
        qDebug() << "Result: " << displayNumber;
    }
    else if (ui->pushButton_subtract->isChecked())
    {
        qDebug() << "New request: " << firstNum << " - " << secondNum;
        displayNumber = compute(substract,firstNum,secondNum);
        DisplayText = QString::number(displayNumber,'g',15);
        ui->display->setText(DisplayText);
        ui->pushButton_subtract->setChecked(false);
        qDebug() << "Result: " << displayNumber;
    }
    else if (ui->pushButton_mult->isChecked())
    {
        qDebug() << "New request: " << firstNum << " * " << secondNum;
        displayNumber = compute(mult,firstNum,secondNum);;
        DisplayText = QString::number(displayNumber,'g',15);
        ui->display->setText(DisplayText);
        ui->pushButton_mult->setChecked(false);
        qDebug() << "Result: " << displayNumber;
    }
    else if (ui->pushButton_divide->isChecked())
    {
        qDebug() << "New request: " << firstNum << " / " << secondNum;
        try
        {
            displayNumber = compute(divide,firstNum,secondNum);;
            if (secondNum == 0.0) {
                throw 1; 
            }
            DisplayText = QString::number(displayNumber,'g',15);
            ui->display->setText(DisplayText);
            ui->pushButton_divide->setChecked(false);
            qDebug() << "Result: " << displayNumber;
        }
        catch (int e)
        {
            qDebug() << "Error: You cannot divide by zero!";
        }
        ui->pushButton_divide->setChecked(false); //чтобы можно было продолжить пользоваться программой, после деления на 0
    }
    userTypingSecondDigit = false;
}
double MainWindow::compute(int Type, double OperandA, double OperandB)
{
    switch (Type) {
        case add:
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
            return OperandA + OperandB;
        }
        case substract:
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
            return OperandA - OperandB;
        }
        case mult:
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
            return OperandA * OperandB;
        }
        case divide:
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
            return OperandA / OperandB;
        }
    }
}

Просьба помочь разобраться с данной задачей. QT для меня в новинку

Answer 1

На текущий момент есть удобное API для работы с потоками, именуемое QFuture.

Для запуска задачи в новом потоке используется QtConcurrent::run(). Эта функция возвращает экземпляр класса QFuture, с которым легко провести ожидание результата и тд.

Так же, есть готовый класс для синхронизации потоков, который позволяет дождаться результата выполнения нескольких операций без сигналов и слотов.

READ ALSO
Запись и чтение из COM порта Linux

Запись и чтение из COM порта Linux

Хочу записать в com-порт и прочитать из него некоторое количество байтС записью проблем вроде бы нет, write ошибок не возвращает

128
Проблема с выводом [закрыт]

Проблема с выводом [закрыт]

Только недавно начал изучать Java и решил сделать простенькую игру по угадыванию буквы, но столкнулся с небольшой проблемой, подскажите, в чём...

124
RequestMapping не работает, хотя GetMapping или PostMapping работают

RequestMapping не работает, хотя GetMapping или PostMapping работают

У меня есть Spring MVC приложение, когда я заменяю @GetMapping("/addPhoto") на RequestMapping(name = "/addPhoto",method = RequestMethodGET) у мене просто не стратует программа

131
Фрейм и менеджеры компановки

Фрейм и менеджеры компановки

Можно ли установить для фрейма другой менеджер компановки? Например:

103