QTimer в потоке - события не обрабатываются? - PullRequest
2 голосов
/ 30 июля 2010

У меня есть объект, производный от QThread, и определение класса включает макрос Q_OBJECT. Я создал таймер в потоке, чтобы можно было время от времени проверять, когда поток работает; однако событие тайм-аута никогда не происходит.

Я также пытался сделать таймер одиночным снимком, но события не генерируются.

События обрабатываются в потоке по умолчанию или мне нужно что-то еще сделать, чтобы они обрабатывались?

Вот код для настройки потока и таймеров:

void MyClass::run( void ) 
{ 
    checkTimer_chA = new QTimer( this ); 

    qDebug() << connect( checkTimer_chA, SIGNAL( timeout() ), this, SLOT( timerExpiry_chA() ) ); 

    checkTimer_chA->start( 1000 ); 

    // prevent multiple, simultaneous starts 
    if( !isRunning ) 
    { 
        qDebug() << "Thread: MyClass::run"; 
        isRunning = true; 

        while( isRunning ) 
        { 
            getData(); 
            processData(); 
            yieldCurrentThread(); 
        } 
    } 

    checkTimer_chA->stop(); 

    delete checkTimer_chA; 
}


void DAQ::timerExpiry_chA( void )
{
    qDebug() << "timerExpiry_chA";
    checkTimer_chA->stop();
}

Если я добавлю QApplication :: processEvents (); прямо перед вызовом yieldCurrentThread (); таймер работает, как и ожидалось. Однако мне это кажется неправильным.

Ответы [ 3 ]

6 голосов
/ 31 июля 2010

Работа с потоками в Qt иногда может быть немного хлопотной. Это сообщение в блоге действительно открыло мне глаза.В случае, если мы примем стиль, предложенный в сообщении блога, к вашей проблеме, мы получим решение, подобное приведенному ниже.

Consumer::Consumer():
  checkTimer_(new QTimer(this))
{
    QObject::connect(checkTimer_, SIGNAL(timeout()), this, SLOT(onTimerExpiration());
    QObject::connect(this, SIGNAL(ready()), this, SLOT(consume());
}

bool Consumer::event(QEvent *e)
{
    if (e->type() == QEvent::ThreadChange)
    {
        QTimer::singleShot(0, this, SLOT(start());
    }

    return QObject::event(e);
}

void Consumer::consume()
{
    getData();
    processData();
    emit ready();
}

void Consumer::start()
{
    checkTimer_->start(1000);
    emit ready();
}

void Consumer::onTimerExpiration()
{
    qDebug() << "timeout";
}

Затем запустите его в отдельной теме следующим образом:

...
Consumer *consumer = new Consumer();
...
QThread *thread = new QThread(this);
thread->start();
consumer->moveToThread(thread);

Все дочерние объекты Consumer будут выполняться в контексте потока, в который Consumer был перемещен.Можно создать сигнал тайм-аута для класса Consumer и связать его с объектом, который не работает в thread.Qt гарантирует, что надлежащие типы сигналов / слотов будут применены к соединению после перемещения объекта в поток.

Я пропустил всю часть isRunning, так как сомневаюсь, что она вам все еще нужна, покавы создаете только один Consumer.

2 голосов
/ 31 июля 2010

Потоки не имеют своих собственных циклов событий, если вы явно не создаете в них циклы событий. Подробнее см. http://doc.qt.io/qt-5/threads-qobject.html#per-thread-event-loop.

1 голос
/ 31 июля 2010

Возможно, вам нужен цикл обработки событий в потоке.Как насчет изменения кода на следующий?

void MyClass::run( void )
{ 
    checkTimer_chA = new QTimer( this ); 

    qDebug() << connect( checkTimer_chA, SIGNAL( timeout() ), this, SLOT( timerExpiry_chA() ) ); 

    checkTimer_chA->start( 1000 ); 

    // prevent multiple, simultaneous starts 
    if( !isRunning ) 
    { 
        qDebug() << "Thread: MyClass::run";
        isRunning = true;

        QTimer::singleShot(0, this, SLOT(process()));
        exec();
    }

    checkTimer_chA->stop(); 

    delete checkTimer_chA;
}

void MyClass::process()
{
    if( isRunning )
    {
        getData();
        processData();
        yieldCurrentThread();
        QTimer::singleShot(0, this, SLOT(process()));
    }
    else
        QThread::exit();
}

void MyClass::timerExpiry_chA( void )
{
    qDebug() << "timerExpiry_chA";
    checkTimer_chA->stop();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...