Russian Qt Forum
Ноябрь 22, 2024, 16:48 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QEventDispatcherWin32::registerTimer: Failed to create a timer  (Прочитано 4157 раз)
copyguk
Новичок

Offline Offline

Сообщений: 9


Просмотр профиля
« : Сентябрь 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 (Текущий процесс использовал все системные разрешения по управлению объектами диспетчера окон.)
и отжирать оперативную память.
Код не очень, но должен отрабатывать верно. Где косяк?
Записан
copyguk
Новичок

Offline Offline

Сообщений: 9


Просмотр профиля
« Ответ #1 : Сентябрь 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;
}

Записан
copyguk
Новичок

Offline Offline

Сообщений: 9


Просмотр профиля
« Ответ #2 : Сентябрь 09, 2021, 10:53 »

Вложения
Записан
copyguk
Новичок

Offline Offline

Сообщений: 9


Просмотр профиля
« Ответ #3 : Сентябрь 10, 2021, 08:52 »

Опытным путем выяснил, что QNetworkAccessManager несколько раз отправляет сигнал finished. Поиск в интернете привел к:
https://stackoverflow.com/questions/13803476/qnetworkaccessmanager-sends-get-two-times

Хотя там другая, но схожая проблема. Плтаформа Windows 7x64, Qt 6.1.3. Есть хоть какие-то мысли?
Записан
copyguk
Новичок

Offline Offline

Сообщений: 9


Просмотр профиля
« Ответ #4 : Сентябрь 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;
    }
Закоментировал еще один вызов таймера. Пока работает без нареканий и не течет. Если за пару все будет работать тему помечу как решенную.
Записан
copyguk
Новичок

Offline Offline

Сообщений: 9


Просмотр профиля
« Ответ #5 : Сентябрь 10, 2021, 09:30 »

UPD:
Количество ответов увеличивается, и все они кроме последнего пустые. За счет этого программа незначительно течет. При запуске занимаемая память примерно 19 мегабайт, после 20 минут работы - больше 22. Не критично, но хотелось бы починить.
« Последнее редактирование: Сентябрь 10, 2021, 09:34 от copyguk » Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #6 : Сентябрь 10, 2021, 10:24 »

Ну
Код
C++ (Qt)
reply->deleteLater()
ещё бы нужно вызвать.
Записан
copyguk
Новичок

Offline Offline

Сообщений: 9


Просмотр профиля
« Ответ #7 : Сентябрь 10, 2021, 11:56 »

Добавил deleteLater. Получилось

Код:
    reply->disconnect();
    reply->close();
    reply->deleteLater();

Также приходит сигнал с пустым содержимым.
Записан
copyguk
Новичок

Offline Offline

Сообщений: 9


Просмотр профиля
« Ответ #8 : Сентябрь 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();

Сейчас вроде нет ни утечек ни лишних сигналов с пустым ответом. Подскажите, это корректное решение и возможны ли подводные камни. Внес много изменений, поэтому выкладываю новый проект.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.063 секунд. Запросов: 22.