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

C++, Qt

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

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

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

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

  1. void MainWindow::equal_pressed()
  2. {
  3. double displayNumber;
  4. double secondNum = ui->display->text().toDouble();
  5. QString DisplayText;
  6.  
  7. if (ui->pushButton_add->isChecked())
  8. {
  9. qDebug() << "New request: " << firstNum << " + " << secondNum;
  10. std::thread thread_2([&displayNumber,secondNum,this](){displayNumber = compute(add,firstNum,secondNum); });
  11. thread_2.join(); // это конечно неправильно, выходит тоже самое что и в одном потоке. Где-то нужно создать std::queue мб и туда помещать запросы
  12. DisplayText = QString::number(displayNumber,'g',15); // только как.
  13. ui->display->setText(DisplayText);
  14. ui->pushButton_add->setChecked(false);
  15. qDebug() << "Result: " << displayNumber;
  16. }
  17. else if (ui->pushButton_subtract->isChecked())
  18. {
  19. qDebug() << "New request: " << firstNum << " - " << secondNum;
  20. displayNumber = compute(substract,firstNum,secondNum);
  21. DisplayText = QString::number(displayNumber,'g',15);
  22. ui->display->setText(DisplayText);
  23. ui->pushButton_subtract->setChecked(false);
  24. qDebug() << "Result: " << displayNumber;
  25. }
  26. else if (ui->pushButton_mult->isChecked())
  27. {
  28. qDebug() << "New request: " << firstNum << " * " << secondNum;
  29. displayNumber = compute(mult,firstNum,secondNum);;
  30. DisplayText = QString::number(displayNumber,'g',15);
  31. ui->display->setText(DisplayText);
  32. ui->pushButton_mult->setChecked(false);
  33. qDebug() << "Result: " << displayNumber;
  34. }
  35. else if (ui->pushButton_divide->isChecked())
  36. {
  37. qDebug() << "New request: " << firstNum << " / " << secondNum;
  38. try
  39. {
  40. displayNumber = compute(divide,firstNum,secondNum);;
  41. if (secondNum == 0.0) {throw 1; }
  42. DisplayText = QString::number(displayNumber,'g',15);
  43. ui->display->setText(DisplayText);
  44. ui->pushButton_divide->setChecked(false);
  45. qDebug() << "Result: " << displayNumber;
  46. }
  47. catch (int e)
  48. {
  49. qDebug() << "Error: You cannot divide by zero!";
  50. }
  51. ui->pushButton_divide->setChecked(false); //чтобы можно было продолжить пользоваться программой, после деления на 0
  52. }
  53.  
  54. userTypingSecondDigit = false;
  55. }
  56.  
  57. double MainWindow::compute(int Type, double OperandA, double OperandB)
  58. {
  59. switch (Type) {
  60. case add:
  61. {
  62. std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
  63. return OperandA + OperandB;
  64. }
  65. case substract:
  66. {
  67. std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
  68. return OperandA - OperandB;
  69. }
  70. case mult:
  71. {
  72. std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
  73. return OperandA * OperandB;
  74. }
  75. case divide:
  76. {
  77. std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
  78. return OperandA / OperandB;
  79. }
  80. }
  81. }

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

1

Do you like it? Share on social networks!

1
Evgenii Legotckoi
  • Jan. 29, 2019, 1:52 p.m.
  • (edited)

Добрый день!

Думаю, что вы можете воспользоваться QThread::moveToThread , как показано в статье.

Я бы на вашем месте создал класс внутренней логики калькулятора, который с помощью moveToThread будет передаваться в другой поток. Данный класс будет иметь свою рабочую петлю в которой будет ожидать данные для расчёта, данные можно будет помещать в QQueue с помощью сигнал/слотового соединения, аналогично извлекать данные с помощью сигнал слотового соединения. Соответственно в слотах нужно будет использовать QMutex, чтобы обезопасить данные.

    Comments

    Only authorized users can post comments.
    Please, Log in or Sign up
    • Last comments
    • AK
      April 1, 2025, 11:41 a.m.
      Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
    • Evgenii Legotckoi
      March 9, 2025, 9:02 p.m.
      К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
    • VP
      March 9, 2025, 4:14 p.m.
      Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
    • ИМ
      Nov. 22, 2024, 9:51 p.m.
      Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
    • Evgenii Legotckoi
      Oct. 31, 2024, 11:37 p.m.
      Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup