Страницы

Поиск по вопросам

понедельник, 24 февраля 2020 г.

Завершение работы QRunnable

#cpp #qt #qt5


Использую QThreadPool и QRunnable. Как завершить работу QRunnable, если тот из очереди
уже перешёл в состояние выполнения?

В QThreadPool имеется метод, позволяющий изымать из пула объекты выполнения, но только
тех из них, что всё ещё находятся в очереди.

По идее, в наследнике QRunnable нужен некий флаг (наподобие QThread::requestInterruption()),
который можно было бы переключать из вне, а уже объект выполнения смотрел бы время
от времени значение этого флага. Соответственно, если настала пора закругляться, то
и завершал бы свою работу.

Однако в этом случае нужно хранить список объектов QRunnable, чтобы иметь возможность
установки флага, и в итоге иметь вероятность краха программы, если QThreadPool кого-либо
из них заблаговременно уничтожит. Отказываться от QRunnable::autoDelete() == true совсем
не хочется.

Есть ли возможность как-то решить эту проблему, не уходя в сторону QThread и не изменяя
QRunnable::autoDelete() == true, так как уж очень подкупает удобство использования
QThreadPool?
    


Ответы

Ответ 1



Если Вас не устраивает функция отмены в наследнике QRunnable, тогда можно сделать по другому. Пусть наследник имеет конструктор, который принимает указатель на QAtomicInteger. Ещё будет конструктор, которые не будет принимать этот указатель — по умолчанию, в классе, он будет равен nullptr. Внутри метода run если указатель не нулевой, и его значение по указателю(полученное через load()) равно, скажем, 1, тогда задание было отменено и мы немедленно завершаем выполнение. Как Вы уже поняли, этот указатель будет предоставляться тем кодом, что создаёт QRunnable и его значение будет выставляться там же. Код может выглядеть так: class MyRunnable: public QRunnable { public: MyRunnable(QAtomicInteger* cancelationToken): m_CancelationToken{cancelationToken} { } void run() override { while(true) { if(m_CancelationToken && m_CancelationToken->load() == 1) return; } } private: QAtomicInteger* m_CancelationToken = nullptr; }; Где-то в коде: QAtomicInteger cancel; auto runnable = new MyRunnable(&cancel); ... cancel = 1;

Комментариев нет:

Отправить комментарий