Событие таймера приходит хз куда
От: удусекшл  
Дата: 11.02.21 13:32
Оценка:
Всем привет!

Объект — плагин для CAN, конструктор/деструктор, open/close — этим всем кути заведует, сама вызывает, когда надо, когда в приложении производятся действия с драйвером CAN'а.

В объекте сделал QTimer, приконнектил к слоту.

В open — стартую, в close — выключаю.
Через раз вылезает исключение — пришло событие таймера моему объекту, только адрес на 24 (0x18) отличается, в большую сторону, если это важно.
Сделал отладочную печать везде где можно, вижу, как срабатывает конструктор, как деструктор, как open/close, вижу, что таймер стопариться.

И всё равно прилетает событие таймера.
Переделал, стал connect/disconnect делать при старте/стопе — та же фигня.

Переделал, убрал отдельный таймер, стал использовать QObject::startTimer/QObject::killTimer — та же фигня.

После стопа таймера добавил QCoreApplication::removePostedEvents( this, (int)QEvent::Timer ) — и опять та же фигня.

Чего я не так делаю?
Re: Событие таймера приходит хз куда
От: XOOIOOX  
Дата: 11.02.21 13:40
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>Чего я не так делаю?


Какую роль таймер выполняет? Просто так крутится?

Если что-то по нему должно срабатывать, то connect нужно делать по QTimer::timeout() В методе, куда сконнекчен timeout, таймер стопается. Собственно, все.

Примерно так:

Worker::Worker()
{
    workerTimer = new QTimer;
    connect(workerTimer, &QTimer::timeout, this, &Worker::workerTimerEndSlot);
}

void Worker::startProcessingSlot()
{
    workerTimer->start(100);
}

void Worker::workerTimerEndSlot
{
    workerTimer->stop();
    emit workerStartSignal();
}
Отредактировано 11.02.2021 13:49 XOOIOOX . Предыдущая версия .
Re[2]: Событие таймера приходит хз куда
От: удусекшл  
Дата: 11.02.21 13:49
Оценка:
Здравствуйте, XOOIOOX, Вы писали:

XOO>Какую роль таймер выполняет? Просто так крутится?


По таймеру выгребаются данные из устройства


XOO>Если что-то по нему должно срабатывать, то connect нужно делать по QTimer::timeout() В методе, куда сконнекчен timeout, таймер стопается. Собственно, все.


Ничего не понял
Re[3]: Событие таймера приходит хз куда
От: XOOIOOX  
Дата: 11.02.21 13:53
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>По таймеру выгребаются данные из устройства


Он запускается по событию? Или постоянно с интервалом крутится?
Если последнее, то в слоте привязки таймера по таймауту, после обработки, запускай его заново.

Worker::Worker()
{
    workerTimer = new QTimer;
    connect(workerTimer, &QTimer::timeout, this, &Worker::workerTimerEndSlot);
    workerTimer->start(100);
}

void Worker::workerTimerEndSlot
{
    workerTimer->stop();
    hardWork();
    workerTimer->start(100);
}


У>Ничего не понял


Пред. сообщение дополнил кодом.
Отредактировано 11.02.2021 13:57 XOOIOOX . Предыдущая версия .
Re[4]: Событие таймера приходит хз куда
От: удусекшл  
Дата: 11.02.21 14:22
Оценка:
Здравствуйте, XOOIOOX, Вы писали:


XOO>Он запускается по событию? Или постоянно с интервалом крутится?

XOO>Если последнее, то в слоте привязки таймера по таймауту, после обработки, запускай его заново.

Идея такая, что single shot timer перезапускать ручками в обработчике?

  Скрытый текст
class TimerRestarter
{
public:

    TimerRestarter( QTimer &t ) : m_timer(t)
    {
        m_timer.stop();
    }

    ~TimerRestarter()
    {
        m_timer.setSingleShot(true);
        m_timer.setInterval(50); // 20 times per ec
        m_timer.setTimerType(Qt::CoarseTimer);
        m_timer.start();
    }

protected:

    QTimer &m_timer;

};


Вставил в обработчик таймера
    TimerRestarter timerRestarter(m_pollTimer);


Та же фигня — прилетает событие после разрушения объекта
Re[5]: Событие таймера приходит хз куда
От: XOOIOOX  
Дата: 11.02.21 15:01
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>Вставил в обработчик таймера

У>
У>    TimerRestarter timerRestarter(m_pollTimer);
У>


У>Та же фигня — прилетает событие после разрушения объекта


Так в самом объекте как таймер сконнекчен?
Re[6]: Событие таймера приходит хз куда
От: удусекшл  
Дата: 11.02.21 15:30
Оценка:
Здравствуйте, XOOIOOX, Вы писали:


У>>Та же фигня — прилетает событие после разрушения объекта


XOO>Так в самом объекте как таймер сконнекчен?


Как-то так:

  Скрытый текст
bool CanBackend::open()
{
    QString errorReason;

    setState(QCanBusDevice::ConnectingState);

    bool res = openImpl( errorReason );

    if (res)
    {
        // https://doc.qt.io/qt-5/qtimer.html
        // Alternatives to QTimer

        
        connect(&m_pollTimer, SIGNAL(timeout()), this, SLOT(pollTimerEvent()));

        #if defined(_DEBUG)
            qDebug().nospace().noquote()<<"CP44 - close - timer connected";
        #endif

        m_pollTimer.start();

        #if defined(_DEBUG)
            qDebug().nospace().noquote()<<"CP45 - close - timer started";
        #endif
        
        //timerId = startTimer(50, Qt::CoarseTimer);
        //qDebug().nospace().noquote()<<"Timer started, ID: " << timerId;

        setState(QCanBusDevice::ConnectedState);

    }
    else
    {
        setState(QCanBusDevice::UnconnectedState);
    }

    return res;

}

void CanBackend::close()
{
    QString errorReason;

    disconnect(&m_pollTimer, SIGNAL(timeout()), this, SLOT(pollTimerEvent()));

    setState(QCanBusDevice::ClosingState);

    closeImpl( errorReason );

    setState(QCanBusDevice::UnconnectedState);
}

class TimerRestarter
{
public:

    TimerRestarter( QTimer &t ) : m_timer(t)
    {
        m_timer.stop();
    }

    ~TimerRestarter()
    {
        m_timer.setSingleShot(true);
        m_timer.setInterval(50); // 20 times per ec
        m_timer.setTimerType(Qt::CoarseTimer);
        m_timer.start();
    }

protected:

    QTimer &m_timer;

};

//----------------------------------------------------------------------------

void CanBackend::pollTimerEvent()
{
    if (state()!=QCanBusDevice::ConnectedState)
        return;

    TimerRestarter timerRestarter(m_pollTimer);

    // ...
    // Тут падаем
}
Re[7]: Событие таймера приходит хз куда
От: XOOIOOX  
Дата: 11.02.21 16:18
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>

void CanBackend::pollTimerEvent()
{
    if (state()!=QCanBusDevice::ConnectedState)
        return;
    TimerRestarter timerRestarter(m_pollTimer);

    // ...
    // Тут падаем
}

А если в начало метода TimerRestarter передвинуть?
Re[8]: Событие таймера приходит хз куда
От: удусекшл  
Дата: 11.02.21 16:33
Оценка:
Здравствуйте, XOOIOOX, Вы писали:

У>>

XOO>void CanBackend::pollTimerEvent()
XOO>{
XOO>    if (state()!=QCanBusDevice::ConnectedState)
XOO>        return;
XOO>    TimerRestarter timerRestarter(m_pollTimer);

XOO>    // ...
XOO>    // Тут падаем
XOO>}
XOO>

XOO>А если в начало метода TimerRestarter передвинуть?

Сначала так и было
Re[9]: Событие таймера приходит хз куда
От: XOOIOOX  
Дата: 11.02.21 17:11
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>Сначала так и было


Похоже, что где-то создается копия таймера, которая шлет сигнал на слот.
Можно попробовать добавить флаг Qt::UniqueConnection в соединение.
Re[8]: Событие таймера приходит хз куда
От: Igore Россия  
Дата: 11.02.21 17:13
Оценка:
Здравствуйте, XOOIOOX, Вы писали:

XOO>void CanBackend::pollTimerEvent()

XOO>{
XOO> if (state()!=QCanBusDevice::ConnectedState)
XOO> return;
XOO> TimerRestarter timerRestarter(m_pollTimer);

XOO> // ...

XOO> // Тут падаем

Падать может от того что у тебя CanBackend уже уничтожен, и добавь в
void CanBackend::close()
{
    m_pollTimer.stop();
    //disconnect(&m_pollTimer, SIGNAL(timeout()), this, SLOT(pollTimerEvent()));
    m_pollTimer.disconnect();
}
Re: Событие таймера приходит хз куда
От: Chorkov Россия  
Дата: 15.02.21 09:01
Оценка: 4 (1)
Здравствуйте, удусекшл, Вы писали:

У>Всем привет!


У>Объект — плагин для CAN, конструктор/деструктор, open/close — этим всем кути заведует, сама вызывает, когда надо, когда в приложении производятся действия с драйвером CAN'а.


У>В объекте сделал QTimer, приконнектил к слоту.


У>В open — стартую, в close — выключаю.

У>Через раз вылезает исключение — пришло событие таймера моему объекту, только адрес на 24 (0x18) отличается, в большую сторону, если это важно.

На самом деле, это критическая точка.
Очень похоже на проблемы с таблицей виртуальных функций.
Проверьте список родителей класса CanBackend. (Возможно, наследник QObject-а не первый в списке родителей.)
Адреса this, static_cast<QObject*>(this), dynamic_cast<QObject*>(this) должны совпадать.

Нет ли в определении CanBackend (или родителей), каких-то ifdef которые по разному срабатывают в разных единицах трансляции, или какого-то другого нарушения ODR?

У>Сделал отладочную печать везде где можно, вижу, как срабатывает конструктор, как деструктор, как open/close, вижу, что таймер стопариться.


У>И всё равно прилетает событие таймера.

У>Переделал, стал connect/disconnect делать при старте/стопе — та же фигня.

У>Переделал, убрал отдельный таймер, стал использовать QObject::startTimer/QObject::killTimer — та же фигня.


У>После стопа таймера добавил QCoreApplication::removePostedEvents( this, (int)QEvent::Timer ) — и опять та же фигня.


У>Чего я не так делаю?


Проверьте какому потоку принадлежат таймер и CanBackend. Возможно, кто-то, например устанавливая родителя, перекинул объект из потока в поток.
Re[10]: Событие таймера приходит хз куда
От: удусекшл  
Дата: 16.02.21 12:44
Оценка:
Здравствуйте, XOOIOOX, Вы писали:

У>>Сначала так и было


XOO>Похоже, что где-то создается копия таймера, которая шлет сигнал на слот.

XOO>Можно попробовать добавить флаг Qt::UniqueConnection в соединение.

Переделал на QSharedPointer<QTimer> — то же самое
Re[2]: Событие таймера приходит хз куда
От: удусекшл  
Дата: 16.02.21 12:47
Оценка:
Здравствуйте, Chorkov, Вы писали:

У>>В open — стартую, в close — выключаю.

У>>Через раз вылезает исключение — пришло событие таймера моему объекту, только адрес на 24 (0x18) отличается, в большую сторону, если это важно.

C>На самом деле, это критическая точка.

C>Очень похоже на проблемы с таблицей виртуальных функций.
C>Проверьте список родителей класса CanBackend. (Возможно, наследник QObject-а не первый в списке родителей.)

QObject — единственный родитель. Со смещением я разобрался — у меня есть подобъект, которому я делегирую работу, и куда передаю событие таймера. Там исключение и происходит. Я просто сначала протупил.


C>Адреса this, static_cast<QObject*>(this), dynamic_cast<QObject*>(this) должны совпадать.


Совпадают


C>Проверьте какому потоку принадлежат таймер и CanBackend. Возможно, кто-то, например устанавливая родителя, перекинул объект из потока в поток.


Везде навставлял вывод ID текущего потока — он один
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.