Идея в наброске - у меня есть _object
с _timer
в стеке (переставлен) и _thread
для них в gui:
#include <QTimer>
#include <QObject>
#include <QMainWindow>
#include <QThread>
#include <QSharedPointer>
#include "appguilogcategories.h"
class SomeClass final : public QObject
{
Q_OBJECT
public:
SomeClass(QObject *parent = nullptr) { /* create _inner, set parent 'this' for them ... */ };
private:
QSharedPointer<SomeInnerClass> _inner;
};
class SomeInnerClass : public QObject
{
Q_OBJECT
public:
SomeInnerClass(QObject *parent = nullptr) : QObject(parent)
{
_timer.setParent(this);
_timer.start();
}
~SomeInnerClass() { _timer.stop(); }
private:
QTimer _timer;
};
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr)
{
_ui->setupUi(this);
setThreadUp();
}
~MainWindow()
{
bool is_thread_active = !_thread.isNull()
&& _thread->isRunning()
&& !_thread->isFinished();
if (is_thread_active) {
_thread->quit();
if (!_thread->wait(200)) {
qCCritical(gui()).noquote() << tr("fuck with it!");
_thread->terminate();
_thread->wait();
}
}
delete _ui;
}
private:
Ui::MainWindow *_ui;
SomeClass _object;
QSharedPointer<QThread> _thread;
int setThreadUp()
{
_thread = QSharedPointer<QThread>(new QThread());
if (_thread.isNull()) {
qCCritical(gui()).noquote() << tr("memory for thread allocation failed!");
return EXIT_FAILURE;
}
_object.moveToThread(_thread.data());
Qt::ConnectionType ct = static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection);
connect(_thread.data(), &QThread::finished , &_object, &SomeObject::deleteLater, ct);
connect(_thread.data(), &QThread::finished , [](){ qCDebug(gui()).noquote() << tr("thread finished"); });
_thread->start();
return EXIT_SUCCESS;
}
}
Проблема в том, что _thread
сначала уничтожается при закрытии окна, а затем _object
& _inner
уничтожается позже с остановкой _timer
. Но _inner
меняет свой поток на 0x0
после _thread
окончательной печати и печати отладчика:
QObject :: killTimer: Таймеры нельзя остановить из другого потока
QObject: : ~ QObject: Таймеры не могут быть остановлены из другого потока
Итак, как правильно очистить QObject
с QTimer
в глубине в QThread
ИЛИ как уничтожить QObject
до QThread
ИЛИ Реорганизовать этот эскиз?
PS: SomeClass - контроллер устройства (рабочий), SomeInnerClass - контроллер порта, QTimer - контролер пакетов. При закрытии окна отключите устройство с контроллером уничтожения.