М
Миша16 декабря 2017 г. 12:11

Пауза в многопоточности

Здравствуйте, можно ли поставить процесс на паузу при выполнении функций в многопоточности QtConcurrent::map?

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

18
Evgenii Legotckoi
  • 16 декабря 2017 г. 12:23
  • (ред.)

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


Но для QtConcurrent::run, например, в документации сказано, что пауза и возобновление для QFuture поддерживаться не будут. Однако для QtConcurrent::map такого не сказано.

Поэтому просто проверьте, будут ли работать те методы. Если будут работать, то всё ОК, если не будут, значит это также как и для QtConcurrent::run не поддерживается.
    М
    • 17 декабря 2017 г. 2:30

    Во  время работы поверх окна приложения активно окно QProgressDialog. И у него есть только одна кнопка. Код выглядит следующим образом. Можно ли добавить еще две кнопки или диалог баттон бокс в окно QProgressDialog? Или можно как то иначе произвести сигнал?

    QProgressDialog dialog;
    
           // Создать объект QFutureWatcher и подключить сигналы и слоты к диалогу.
           // Мониторинг прогресса изменений для future
           QFutureWatcher<void> futureWatcher;
           connect(&futureWatcher, &QFutureWatcher<void>::finished, &dialog, &QProgressDialog::reset);
           connect(&dialog, &QProgressDialog::canceled, &futureWatcher, &QFutureWatcher<void>::cancel);
           connect(&dialog, &QProgressDialog::canceled,[this](){StopStrategy=true;});
           connect(&futureWatcher, &QFutureWatcher<void>::progressRangeChanged, &dialog, &QProgressDialog::setRange);
           connect(&futureWatcher, &QFutureWatcher<void>::progressValueChanged, &dialog, &QProgressDialog::setValue);
    
    
    
           //QFuture<void> Perebor1 = QtConcurrent::map(Perebor,[this](const double& d){ StrategyCod2(d);});  //просчет стратегии в нескольхих потоках
           FileForRecord.open(QIODevice::WriteOnly);  //открывает файл на запись
    
           QLibrary MyLib("C:\\Qt\\project\\build-StrategyCod-Desktop_Qt_5_9_2_MinGW_32bit-Debug\\debug\\StrategyCod");  //путь к библиотеке
           MyLib.unload();//отключение библиотеки
           MyLib.load();//чтение
           typedef void (*MyPrototype)(double,MainWindow *);
           MyPrototype StrategyCod = (MyPrototype) MyLib.resolve("StrategyCod");
           futureWatcher.setFuture(QtConcurrent::map(Perebor,[=](const double& d){ StrategyCod(d,this);}));
           // Показать диалог и запустить программную петлю диалога
           dialog.exec();
    
           futureWatcher.waitForFinished();
           MyLib.unload();//отключение библиотеки

     

      Evgenii Legotckoi
      • 17 декабря 2017 г. 4:55

      Если честно, здесь уже проще самому написать нужный класс.

      Дело в том, что QProgressDialog не имеет QDialogButtonBox , как впрочем и QDialog . Да, в QProgressDialog есть кнопка отмена , но только она там и есть. А QDialog вообще не имеет кнопок и QDialogButtonBox`а .
      Но QDialog используется как база для создания своих диалоговых окон.
      Так что на мой взгляд, проще создать свой прогресс диалог и реализовать самостоятельно весь необходимый функционал. В конце концов есть и отдельный виджет прогресс бара, который можно использовать в собственном диалоге.
      Ещё можно, конечно, наследоваться от QProgressDialog`a, но скорее всего это будет несколько более усложнённым решением в плане вёрстки.
        М
        • 18 декабря 2017 г. 8:03

        У меня есть QProgressBar "ui->ProgressBar2".

        Можно ли ему аналогично передавать значение объема?
        Могу написать так
        connect (& futureWatcher, & QFutureWatcher <void> :: progressValueChanged, [=](){ui->ProgressBar2->setValue(25);});
        Но как задать значение прогресса?
        Если пишу так, то сразу 10 ошибок
        connect (& futureWatcher, & QFutureWatcher <void> :: progressValueChanged, [=](){ui->ProgressBar2->setValue(25);qDebug()<<futureWatcher.progressValue();});

          Evgenii Legotckoi
          • 18 декабря 2017 г. 8:11

          Киньте текст ошибок. Хотя у меня подозрение, что вы просто забыли/удалили #include <QDebug>

            М
            • 18 декабря 2017 г. 8:13
            C:\Qt\project\MyCandleSrick\mainwindow.cpp:1116: ошибка: use of deleted function 'QFutureWatcher<void>::QFutureWatcher(const QFutureWatcher<void>&)'
            connect (& futureWatcher, & QFutureWatcher <void> :: progressValueChanged, [=](){ui->ProgressBar2->setValue(25);qDebug()<<futureWatcher.progressValue();});
            ^
            C:\Qt\Qt5.9.2\5.9.2\mingw53_32\include\QtCore\qfuturewatcher.h:185: ошибка: use of deleted function 'QFutureWatcherBase::QFutureWatcherBase(const QFutureWatcherBase&)'
            C:\Qt\Qt5.9.2\5.9.2\mingw53_32\include\QtCore\qobject.h:454: ошибка: 'QObject::QObject(const QObject&)' is private
            Q_DISABLE_COPY(QObject)
            ^
            C:\Qt\Qt5.9.2\5.9.2\mingw53_32\include\QtCore\qfuturewatcher.h:55: ошибка: within this context
            class Q_CORE_EXPORT QFutureWatcherBase : public QObject
            ^
            C:\Qt\Qt5.9.2\5.9.2\mingw53_32\include\QtCore\qfuturewatcher.h:55: ошибка: use of deleted function 'QObject::QObject(const QObject&)'
            C:\Qt\project\MyCandleSrick\mainwindow.cpp:1116: ошибка: use of deleted function 'MainWindow::on_ButtonRunMulti_clicked()::<lambda()>::<lambda>(MainWindow::on_ButtonRunMulti_clicked()::<lambda()>&&)'
            connect (& futureWatcher, & QFutureWatcher <void> :: progressValueChanged, [=](){ui->ProgressBar2->setValue(25);qDebug()<<futureWatcher.progressValue();});
            ^
            C:\Qt\project\MyCandleSrick\mainwindow.cpp:1116: ошибка: use of deleted function 'QFutureWatcher<void>::QFutureWatcher(const QFutureWatcher<void>&)'
            C:\Qt\Qt5.9.2\5.9.2\mingw53_32\include\QtCore\qobject.h:307: ошибка: use of deleted function 'MainWindow::on_ButtonRunMulti_clicked()::<lambda()>::<lambda>(const MainWindow::on_ButtonRunMulti_clicked()::<lambda()>&)'
            return connect(sender, signal, sender, slot, Qt::DirectConnection);
            ^
            C:\Qt\project\MyCandleSrick\mainwindow.cpp:1116: ошибка: use of deleted function 'QFutureWatcher<void>::QFutureWatcher(const QFutureWatcher<void>&)'
            C:\Qt\Qt5.9.2\5.9.2\mingw53_32\include\QtCore\qobject.h:313: ошибка: 'static typename std::enable_if<(QtPrivate::FunctionPointer<Func2>::ArgumentCount == (-1)), QMetaObject::Connection>::type QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, const QObject*, Func2, Qt::ConnectionType) [with Func1 = void (QFutureWatcherBase::*)(int); Func2 = MainWindow::on_ButtonRunMulti_clicked()::<lambda()>; typename std::enable_if<(QtPrivate::FunctionPointer<Func2>::ArgumentCount == (-1)), QMetaObject::Connection>::type = QMetaObject::Connection; typename QtPrivate::FunctionPointer<Func>::Object = QFutureWatcherBase]', declared using local type 'MainWindow::on_ButtonRunMulti_clicked()::<lambda()>', is used but never defined [-fpermissive]

              Evgenii Legotckoi
              • 18 декабря 2017 г. 8:13

              А вообще, можно и сигнал/слотовое соединение переписать.

              connect (& futureWatcher, & QFutureWatcher <void> :: progressValueChanged, [=](int progressValue){ui->ProgressBar2->setValue(progressValue);});
              Сигнал же уже в качестве аргумента передаёт изменение прогресса.
                М
                • 18 декабря 2017 г. 8:22

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


                  Evgenii Legotckoi
                  • 18 декабря 2017 г. 8:28
                  • (ред.)

                  Я конечно сталкивался с тем, что некоторый функционал Qt не работает под некоторыми ОС, но то, что не передаётся информация о прогрессе из QFuture - это сомнительно. А вы устанавливаете диапазон значений для прогресс бара?

                  connect(&futureWatcher, &QFutureWatcher<void>::progressRangeChanged, ui->ProgressBar2, &QProgressBar::setRange);
                  Возможно из-за того, что значения диапазона изначально не определены, то и значения текущего прогресса, передаваемые из QFuture, являются ошибочными.
                    М
                    • 18 декабря 2017 г. 8:35

                    оно у меня стоит от 0 до 100

                    сделал так, все еще не работает
                    connect (& futureWatcher, & QFutureWatcher <void> :: progressRangeChanged,  ui->ProgressBar2, & QProgressBar::setRange);
                    connect (& futureWatcher, & QFutureWatcher <void> :: progressValueChanged,  ui->ProgressBar2, & QProgressBar :: setValue)
                      Evgenii Legotckoi
                      • 18 декабря 2017 г. 8:36

                      Что касается этой ошибки, то по факту здесь запрещено копирование QFuture объекта, которое происходит в данном коде.
                      Можно переписать так для данной лямбды.

                      connect (& futureWatcher, & QFutureWatcher <void> :: progressValueChanged, 
                      [this, &futureWatcher](){ui->ProgressBar2->setValue(25);qDebug()<<futureWatcher.progressValue();});
                        М
                        • 18 декабря 2017 г. 8:38

                        может быть мое окно не активно, пока работает

                        futureWatcher.setFuture(QtConcurrent::map(Perebor,[=](const double& d){ StrategyCod(d,this); }));
                          М
                          • 18 декабря 2017 г. 8:44

                          Все работает если включить dialog.exec(); . Но как сделать так, что бы работало без диалогового окна?

                            Evgenii Legotckoi
                            • 18 декабря 2017 г. 8:53

                            То есть вы пытаетесь использовать QProgressBar, а также не удалили код из самого начала этого топика, который относится к QProgressDialog?

                            ... Тогда понятно. Скорее всего слот у вас выполняется раньше, чем успевает закончится расчёт. Диалог QProgressDialog нужно удалять отсюда, если он Вам уже не требуется.
                            А вот задержку выполнения кода можно попробовать сделать через QEventLoop
                            QEventLoop loop;
                            loop.connect(&futureWatcher, QFutureWatcher<void>::finished, &loop, &QEventLoop::exit);
                            // Некоторый код для QtConcurrent
                            futureWatcher.setFuture(QtConcurrent::map(Perebor,[=](const double& d){ StrategyCod(d,this);}));
                            loop.exec()
                              М
                              • 18 декабря 2017 г. 9:06

                              Дописал без

                              loop.connect(&futureWatcher, QFutureWatcher<void>::finished, &loop, &QEventLoop::exit);
                              и заработало
                                Evgenii Legotckoi
                                • 18 декабря 2017 г. 9:09

                                упс... я немного неправильно тот слот написал, ну да ладно... главное, что заработало

                                  М
                                  • 18 декабря 2017 г. 9:27
                                  • (ред.)

                                  Сделал так

                                  connect ( ui->ButtonStopMulti,  &QPushButton::clicked, &futureWatcher, &QFutureWatcher<void>::pause); //пауза процесса
                                  connect ( ui->ButtonRunMulti,  &QPushButton::clicked,  &futureWatcher, &QFutureWatcher<void>::resume);  //продолжение процесса
                                  и все наконец заработало. Большое спасибо.

                                    Evgenii Legotckoi
                                    • 18 декабря 2017 г. 9:34

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

                                    Закиньте вывод qDebug() << "check"; в конце слота и посмотрите, если будет вывод, то значит слот завершается. нужно иначе продумывать логику, чтобы объекты не уничтожались раньше времени.

                                      Комментарии

                                      Только авторизованные пользователи могут публиковать комментарии.
                                      Пожалуйста, авторизуйтесь или зарегистрируйтесь
                                      AD

                                      C++ - Тест 004. Указатели, Массивы и Циклы

                                      • Результат:50баллов,
                                      • Очки рейтинга-4
                                      m
                                      • molni99
                                      • 26 октября 2024 г. 1:37

                                      C++ - Тест 004. Указатели, Массивы и Циклы

                                      • Результат:80баллов,
                                      • Очки рейтинга4
                                      m
                                      • molni99
                                      • 26 октября 2024 г. 1:29

                                      C++ - Тест 004. Указатели, Массивы и Циклы

                                      • Результат:20баллов,
                                      • Очки рейтинга-10
                                      Последние комментарии
                                      ИМ
                                      Игорь Максимов22 ноября 2024 г. 11:51
                                      Django - Урок 017. Кастомизированная страница авторизации на Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
                                      Evgenii Legotckoi
                                      Evgenii Legotckoi31 октября 2024 г. 14:37
                                      Django - Урок 064. Как написать расширение для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
                                      A
                                      ALO1ZE19 октября 2024 г. 8:19
                                      Читалка fb3-файлов на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                                      ИМ
                                      Игорь Максимов5 октября 2024 г. 7:51
                                      Django - Урок 064. Как написать расширение для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                                      d
                                      dblas55 июля 2024 г. 11:02
                                      QML - Урок 016. База данных SQLite и работа с ней в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                                      Сейчас обсуждают на форуме
                                      Evgenii Legotckoi
                                      Evgenii Legotckoi24 июня 2024 г. 15:11
                                      добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                                      t
                                      tonypeachey115 ноября 2024 г. 6:04
                                      google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
                                      NSProject
                                      NSProject4 июня 2022 г. 3:49
                                      Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
                                      9
                                      9Anonim25 октября 2024 г. 9:10
                                      Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

                                      Следите за нами в социальных сетях