Название: QEventDispatcherWin32::registerTimer: Failed to create a timer
Отправлено: copyguk от Сентябрь 09, 2021, 09:59
Пишу программу для проверки по инн на самозанятость с использованием API ФНС (https://data.nalog.ru/html/sites/www.npd.nalog.ru/api_statusnpd_nalog_ru.pdf). При работе, через некоторое время начинает сыпать ошибкой: QEventDispatcherWin32::registerTimer: Failed to create a timer (Текущий процесс использовал все системные разрешения по управлению объектами диспетчера окон.) и отжирать оперативную память. Код не очень, но должен отрабатывать верно. Где косяк?
Название: Re: QEventDispatcherWin32::registerTimer: Failed to create a timer
Отправлено: copyguk от Сентябрь 09, 2021, 10:02
Код mainwindows.h #ifndef MAINWINDOW_H #define MAINWINDOW_H
#include <QMainWindow> #include "QTimer" #include "QNetworkReply"
QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE
class MainWindow : public QMainWindow { Q_OBJECT
public: MainWindow(QWidget *parent = nullptr); ~MainWindow();
private slots: void on_action_4_triggered();
void on_action_triggered();
int kor_inn(QString inn_nomber);
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void onGet(QNetworkReply* reply);
void post();
void onError(QNetworkReply::NetworkError);
private: Ui::MainWindow *ui;
QTimer *pausa_do_zaprosa= new QTimer(0);
QNetworkAccessManager *manager;
}; #endif // MAINWINDOW_H
Код mainwindows.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include "QMessageBox" #include "QFileDialog" #include "QNetworkAccessManager" #include "QNetworkRequest" #include "QNetworkReply" #include "QSsl" #include "QUrlQuery" #include "QRegularExpression" #include "QHttpPart" #include "QHttpMultiPart" #include "QThread" #include "QSslSocket" #include "QSslConfiguration" #include "QJsonObject" #include "QJsonDocument" #include "QJsonParseError"
int z=0; QStringList perechen_inn, bad_inn, sz, oshibka; bool stop=false; QString temp_inn; QTimer *otvet_servera= new QTimer(0); QString inn_on_block="";
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); ui->calendarWidget->setSelectedDate(QDate::currentDate()); ui->pushButton->setEnabled(false); ui->pushButton_2->setEnabled(false); ui->pushButton_3->setEnabled(false); manager = new QNetworkAccessManager(0); }
MainWindow::~MainWindow() { delete ui; }
void MainWindow::on_action_4_triggered() { qApp->exit(0); }
int MainWindow::kor_inn(QString inn_nomber) { //char nomber[10]={0,1,2,3,4,5,6,7,8,9}; QString inn=inn_nomber; QString a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12; int b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12; inn=inn.trimmed(); int result1, result2; if (inn.length()<1){ return 1; //пустая строка } if (inn.length()<12){ return 2; //нехватает символов } if (inn.length()>12){ return 3; //много символов символов } bool nomber=false; inn.toLong(&nomber, 10); if (nomber){ return 4; } /*СПАГЕТИ КОД ТРЕБУЕТСЯ УПРОЩЕНИЕ*/ a1=inn[0]; a2=inn[1]; a3=inn[2]; a4=inn[3]; a5=inn[4]; a6=inn[5]; a7=inn[6]; a8=inn[7]; a9=inn[8]; a10=inn[9]; a11=inn[10]; a12=inn[11]; b1=a1.toInt(); b2=a2.toInt(); b3=a3.toInt(); b4=a4.toInt(); b5=a5.toInt(); b6=a6.toInt(); b7=a7.toInt(); b8=a8.toInt(); b9=a9.toInt(); b10=a10.toInt(); b11=a11.toInt(); b12=a12.toInt(); //result=int(line[0])*7+int(line[1])*2+int(line[2])*4+int(line[3])*10+int(line[4])*3+int(line[5])*5+int(line[6])*9+int(line[7])*4+int(line[8])*6+int(line[9])*8 //result2=int(line[0])*3+int(line[1])*7+int(line[2])*2+int(line[3])*4+int(line[4])*10+int(line[5])*3+int(line[6])*5+int(line[7])*9+int(line[8])*4+int(line[9])*6+int(line[10])*8 result1=(b1*7+b2*2+b3*4+b4*10+b5*3+b6*5+b7*9+b8*4+b9*6+b10*8)%11; result2=(b1*3+b2*7+b3*2+b4*4+b5*10+b6*3+b7*5+b8*9+b9*4+b10*6+b11*8)%11; if (result1>9) result1=result1%10; if (result2>9) result2=result2%10; if ((result1!=b11)||(result2!=b12)){ return 5; //не совпадает контрольная сумма } /*СПАГЕТИ КОД ТРЕБУЕТСЯ УПРОЩЕНИЕ ЗАКОНЧИЛСЯ*/ return 0; }
void MainWindow::onError(QNetworkReply::NetworkError){ qDebug()<<"error"; }
void MainWindow::post() { pausa_do_zaprosa->stop(); ui->label_4->setText("Проверяю "+perechen_inn.first()); if (perechen_inn.length()==0){ stop=true; ui->label_4->setText("Проверка завершена"); } inn_on_block="";
if (!stop){ QUrl url("https://statusnpd.nalog.ru/api/v1/tracker/taxpayer_status"); QNetworkRequest request(url); request.setRawHeader("Content-Type","application/json"); QJsonObject inn_date; inn_date["inn"]=perechen_inn.first().simplified(); inn_date["requestDate"]=ui->calendarWidget->selectedDate().toString("yyyy-MM-dd"); QByteArray postDataByteArray; QSslSocket sslSocket; QSslConfiguration config = sslSocket.sslConfiguration(); config.setProtocol(QSsl::TlsV1_0); request.setSslConfiguration(config); QJsonDocument tempjsondoc(inn_date); postDataByteArray.clear(); postDataByteArray=tempjsondoc.toJson(); manager->post(request,postDataByteArray); connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onGet(QNetworkReply*))); } }
void MainWindow::onGet(QNetworkReply* reply) {
QByteArray bts = reply->readAll(); reply->disconnect(); reply->close(); pausa_do_zaprosa->stop(); if (inn_on_block!=""){ pausa_do_zaprosa->singleShot(40000, this, SLOT(post())); return; } //manager->clearConnectionCache(); if (bts==""){ qDebug()<<"Упс"; oshibka.append(perechen_inn.first()); perechen_inn.removeFirst(); ui->listWidget->clear(); ui->listWidget->addItems(perechen_inn); ui->listWidget_4->clear(); ui->listWidget_4->addItems(oshibka); pausa_do_zaprosa->singleShot(40000, this, SLOT(post())); return; } inn_on_block=perechen_inn.first(); //delete manager;
QJsonDocument jsonDoc; QJsonParseError parseError; jsonDoc = QJsonDocument::fromJson(bts, &parseError); QJsonObject jsonObj=jsonDoc.object(); if (jsonObj.value("code")=="taxpayer.status.service.limited.error"){ pausa_do_zaprosa->singleShot(200000, this, SLOT(post())); return ; } if (jsonObj.value("code")=="taxpayer.status.service.unavailable.error"){ ui->label_4->setText("Сервис временно недоступен"); ui->pushButton_2->click(); return ; } if (jsonObj.value("code")=="validation.failed") bad_inn.append(perechen_inn.first()); if (jsonObj.value("status")==true) sz.append(perechen_inn.first()); qDebug()<<jsonDoc; ui->listWidget_4->clear(); ui->listWidget_4->addItems(oshibka); ui->listWidget_3->clear(); ui->listWidget_3->addItems(sz); perechen_inn.removeFirst(); ui->listWidget->clear(); ui->listWidget->addItems(perechen_inn); pausa_do_zaprosa->singleShot(40000, this, SLOT(post())); }
void MainWindow::on_action_triggered() {
perechen_inn.clear(); int i=0; bad_inn.clear(); sz.clear(); ui->pushButton->setEnabled(true); QString filenametoimport=QFileDialog::getOpenFileName(this, "Выберите файл с переченем ИНН без заголовков", "C:\\"); QFile filetoimport(filenametoimport); QString temp; if (filetoimport.open(QIODevice::ReadOnly)){ temp=filetoimport.readAll(); perechen_inn=temp.split('\n');
filetoimport.close(); } while (perechen_inn.length()>i) { if (!(kor_inn(perechen_inn.at(i))==0)) { bad_inn.append(perechen_inn.at(i)); perechen_inn.removeAt(i); } else { i++; } } ui->listWidget_2->clear(); ui->listWidget_2->addItems(bad_inn); ui->listWidget->clear(); ui->listWidget->addItems(perechen_inn); }
void MainWindow::on_pushButton_clicked() { ui->pushButton->setEnabled(false); ui->pushButton_2->setEnabled(true); ui->pushButton_3->setEnabled(false); stop=false; post(); }
void MainWindow::on_pushButton_2_clicked() { ui->pushButton->setEnabled(true); ui->pushButton_3->setEnabled(true); ui->pushButton_2->setEnabled(false); stop=true; }
Название: Re: QEventDispatcherWin32::registerTimer: Failed to create a timer
Отправлено: copyguk от Сентябрь 09, 2021, 10:53
Вложения
Название: Re: QEventDispatcherWin32::registerTimer: Failed to create a timer
Отправлено: copyguk от Сентябрь 10, 2021, 08:52
Опытным путем выяснил, что QNetworkAccessManager несколько раз отправляет сигнал finished. Поиск в интернете привел к: https://stackoverflow.com/questions/13803476/qnetworkaccessmanager-sends-get-two-times (https://stackoverflow.com/questions/13803476/qnetworkaccessmanager-sends-get-two-times)
Хотя там другая, но схожая проблема. Плтаформа Windows 7x64, Qt 6.1.3. Есть хоть какие-то мысли?
Название: Re: QEventDispatcherWin32::registerTimer: Failed to create a timer
Отправлено: copyguk от Сентябрь 10, 2021, 09:02
Сам задал вопрос, сам ответил: В проверке на повторный сигнал от QNetworkAccessManager еще раз вызывался таймер. Теперь код в функции по обработке ответа выглядит так: void MainWindow::onGet(QNetworkReply* reply) {
QByteArray bts = reply->readAll(); reply->disconnect(); reply->close(); manager->clearAccessCache(); manager->clearConnectionCache(); manager->blockSignals(true); pausa_do_zaprosa->stop(); if (inn_on_block!=""){ //pausa_do_zaprosa->singleShot(40000, this, SLOT(post())); return; } qDebug()<<"Get"; //manager->clearConnectionCache(); if (bts==""){ qDebug()<<"Упс"; oshibka.append(perechen_inn.first()); perechen_inn.removeFirst(); ui->listWidget->clear(); ui->listWidget->addItems(perechen_inn); ui->listWidget_4->clear(); ui->listWidget_4->addItems(oshibka); pausa_do_zaprosa->singleShot(40000, this, SLOT(post())); return; } inn_on_block=perechen_inn.first(); //delete manager;
QJsonDocument jsonDoc; QJsonParseError parseError; jsonDoc = QJsonDocument::fromJson(bts, &parseError); QJsonObject jsonObj=jsonDoc.object(); if (jsonObj.value("code")=="taxpayer.status.service.limited.error"){ pausa_do_zaprosa->singleShot(200000, this, SLOT(post())); return ; } if (jsonObj.value("code")=="taxpayer.status.service.unavailable.error"){ ui->label_4->setText("Сервис временно недоступен"); ui->pushButton_2->click(); return ; } if (jsonObj.value("code")=="validation.failed") bad_inn.append(perechen_inn.first()); if (jsonObj.value("status")==true) sz.append(perechen_inn.first()); qDebug()<<jsonDoc; ui->listWidget_4->clear(); ui->listWidget_4->addItems(oshibka); ui->listWidget_3->clear(); ui->listWidget_3->addItems(sz); perechen_inn.removeFirst(); ui->listWidget->clear(); ui->listWidget->addItems(perechen_inn); pausa_do_zaprosa->singleShot(40000, this, SLOT(post())); }
То есть в if (inn_on_block!=""){ //pausa_do_zaprosa->singleShot(40000, this, SLOT(post())); return; } Закоментировал еще один вызов таймера. Пока работает без нареканий и не течет. Если за пару все будет работать тему помечу как решенную.
Название: Re: QEventDispatcherWin32::registerTimer: Failed to create a timer
Отправлено: copyguk от Сентябрь 10, 2021, 09:30
UPD: Количество ответов увеличивается, и все они кроме последнего пустые. За счет этого программа незначительно течет. При запуске занимаемая память примерно 19 мегабайт, после 20 минут работы - больше 22. Не критично, но хотелось бы починить.
Название: Re: QEventDispatcherWin32::registerTimer: Failed to create a timer
Отправлено: ssoft от Сентябрь 10, 2021, 10:24
Ну C++ (Qt) reply->deleteLater()
ещё бы нужно вызвать.
Название: Re: QEventDispatcherWin32::registerTimer: Failed to create a timer
Отправлено: copyguk от Сентябрь 10, 2021, 11:56
Добавил deleteLater. Получилось reply->disconnect(); reply->close(); reply->deleteLater(); Также приходит сигнал с пустым содержимым.
Название: Re: QEventDispatcherWin32::registerTimer: Failed to create a timer
Отправлено: copyguk от Сентябрь 14, 2021, 09:30
Добавил деструктор QNetworkAccessManager. Получилось: void MainWindow::onGet(QNetworkReply* reply) { QByteArray bts = reply->readAll(); reply->disconnect(); reply->close(); reply->deleteLater(); manager->clearAccessCache(); manager->clearConnectionCache(); manager->blockSignals(true); reply->parent()->destroyed(); Сейчас вроде нет ни утечек ни лишних сигналов с пустым ответом. Подскажите, это корректное решение и возможны ли подводные камни. Внес много изменений, поэтому выкладываю новый проект.
|