Threads,Timer e Atualizar um Campo
-
Pessoal,
Estou precisando de ajuda é a primeira vez que estou trabalhando com threads e acredito que estou fazendo algo errado.
Tenho um arquivo com a seguinte estrutura:@192.168.0.1 executado OK
192.168.0.2 erro Sem_Acesso
192.168.0.3 executado OK
192.168.0.4 executado OK
192.168.0.5 executado OK
192.168.0.6 executado OK
192.168.0.7 executado OK
192.168.0.8 executado OK
192.168.0.9 executado OK
192.168.0.10 executado OK
192.168.0.11 executado OK
192.168.0.12 erro Sem_Acesso
192.168.0.13 erro Não_Responde_na_Rede
192.168.0.14 executado OK@Esse arquivo pode variar de tamanho, por isso estou usando o timer e threads, pois a minha ideia ele faz uma primeira leitura e mostra na tela.
Depois estou tentando usar um thread para rodar em paralelo e um timer para esperar alguns segundos.
mas não estou conseguindo fazer essa atualização.
Segue os códigos:Corrida.h:
@#ifndef CORRIDA_H
#define CORRIDA_H
#include <QThread>
#include <QTimer>class Corrida : public QThread
{
public:
void tempo();
};void Corrida::tempo()
{
QTimer *timer;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(ler_arquivos()));
timer->start(10);
}#endif // CORRIDA_H@
mainwindows.cpp:
@#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "Corrida.h"
#include <QStandardPaths>
#include <QFile>
#include <QMessageBox>
#include <QTextStream>
#include <QDir>
#include <QCoreApplication>
#include <QDebug>
#include <QStandardItem>int coluna =0;
int linha = 1;void ler_arquivos();
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);Corrida tempo; ler_arquivos(); tempo.start(); tempo.wait();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::ler_arquivos()
{
QFile inputFile("C:\log_instalador.txt");
if(inputFile.open(QIODevice::ReadOnly))
{
float cont1 = 0;
float cont2 = 0;
float cont3 = 0;
float cont4 = 0;
float porce = 0;QTextStream in (&inputFile); while (!in.atEnd()){ ui->tableWidget->setRowCount(linha); QString line = in.readLine(); QStringList fields = line.split(" "); QString myS = fields.at(0); QString mySt = fields.at(1); QString myStr = fields.at(2); if(QString::compare(fields.at(1),"executado")==0) { cont1 +=1; } else if(QString::compare(fields.at(1),"erro")==0) { cont2 +=1; } ui->tableWidget->setItem(coluna,0,new QTableWidgetItem(myS)); ui->tableWidget->setItem(coluna,1,new QTableWidgetItem(mySt)); ui->tableWidget->setItem(coluna,2,new QTableWidgetItem(myStr)); coluna += 1; linha += 1; ui->tableWidget->resizeColumnsToContents(); //Dimenciona a celulas cont3 += 1; } porce = ((cont1/cont3)*100); ui->Campo_Verde->setText(QString::number(porce,'f', 0)+" % Executado"); porce = ((cont2/cont3)*100); ui->Campo_Vermelho->setText(QString::number(porce,'f', 0)+" % com Erro"); porce = ((cont1+cont2)-cont3); ui->Campo_Amarelo->setText(QString::number(porce,'f', 0)+" % Resta"); porce = (((cont1/cont3)*100)+((cont2/cont3)*100)); ui->Campo_Status->setText(QString::number(porce,'f', 0)+" % Executado"); qDebug()<< "Quantidade de Executado"; qDebug()<< cont1; qDebug()<< "Quantidade de Erro"; qDebug()<< cont2; qDebug()<< "Quantidade total outros"; qDebug()<< cont4; qDebug()<< "Quantidade total de Linha"; qDebug()<< cont3; } inputFile.close();
}@
Segue em anexo o arquivo do projeto e o .txt que estou usando para testes.
https://docs.google.com/file/d/0BwQ4G9j5uY1Jek90ZVVXRmdReWM/edit?usp=sharing
-
-
Rodrigocg,
Seguindo seu exemplo minha classe .h ficou assim:
@class MyThread : public QThread
{
public:void run();
};
void MyThread::run()
{
QTimer *timer;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(ler_arquivos()));
timer->start(1000);
}@Só que agora recebo a seguinte mensagem:
@QThread: Destroyed while thread is still running@
e no Linux ocorre a seguinte mensagem:
@ASSERT failure in QList<T>::at: "index out of range", file /usr/include/qt5/QtCore/qlist.h, line 454
The program has unexpectedly finished.@E o programa trava, alguma ideia do que ocorre?
-
Rodrigocg,
Agradeço pela ajuda e boa sorte na sua prova. Segue em anexo o link:
https://docs.google.com/file/d/0BwQ4G9j5uY1JQWc5OTloU1RvMzg/edit?usp=sharing
-
Desculpe a demora...
tente implementar a classe MThread assim:
@#ifndef MTHREAD_H
#define MTHREAD_H
#include <QThread>
#include <QTimer>class Mthread: public QThread
{Q_OBJECT
public:
explicit Mthread(QObject *parent = 0): QThread(parent){}
void run()
{
QTimer *timer;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this->parent(), SLOT(leitura()));
timer->start(1000);}
};
#endif // MYTHREAD_H@
Se vc usar o header vc faz do geito que postei assima...
se nao, usa o reader pra prototipar a classe e o arquivo .cpp pra implementar a classe....
-
Vocês precisam tomar cuidado com QObjects (slots) e threads no Qt. Vejam "aqui":http://qt-project.org/doc/qt-4.8/threads-qobject.html.
Em linhas gerais, para que os signal/slots funcionem corretamente, é necessário um "event loop" (um processador de eventos).
É por isso que em todo programa Qt, no main.cpp tem um código parecido com este:
@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();return a.exec(); //Entra num loop infinito, processando e despachando eventos
}
@"If no event loop is running, events won't be delivered to the object. For example, if you create a QTimer object in a thread but never call exec(), the QTimer will never emit its timeout() signal. Calling deleteLater() won't work either. (These restrictions apply to the main thread as well.)"
Tradução Google:
"Se nenhum ciclo de eventos está sendo executado, os eventos não serão entregues ao objeto. Por exemplo, se você criar um objeto QTimer em uma Thread, mas nunca chamar exec (), o QTimer nunca emitem seu sinal de timeout (). Chamando deleteLater () também não vai funcionar. (Estas restrições aplicam-se a thread principal também.)"
-
Se você olhar para o Windows por exemplo, a função da Win32 para timers é a SetTimer - http://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx. E ele posta uma mensagem (no caso WM_TIMER) na fila de mensagens da thread. E no Winsock, existe um modo de funcionamento que não trava as chamadas que usa o loop de mensagens WSAASyncSelect - http://msdn.microsoft.com/en-us/library/windows/desktop/ms741540(v=vs.85).aspx .
É por isso, que se vc usa alguns objetos do Qt não visuais (como o QTimer etc) em threads, é recomendado que você tenha um loop em cada thread.
Aqui no forum sempre rola uns problemas desses....
http://qt-project.org/forums/viewthread/15559 -
Rodrigocg/TioRoy,
Desculpa a demora em responder tive uns problemas que me tomaram um tempo danado.
Rodrigo vou usar o header do jeito que vc me passou mas fiquei na duvida de como executar o mesmo.
Estou deixando assim:@MainWindow::MainWindow(QWidget parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTimer timer = new QTimer;
leitura();
connect(timer, SIGNAL(timeout()), this, SLOT(leitura()));
timer->start(150000);
}@Está correto? Pq não está atualizando os campos que preciso.
O que estou fazendo de errado?