Russian Qt Forum

Qt => XML => Тема начата: Fregloin от Август 05, 2014, 08:10



Название: Прервать парсинг QDomDocument::setContent в отдельном потоке
Отправлено: Fregloin от Август 05, 2014, 08:10
Привет. Столкнулся с такой задачей. У меня в потоке открывается файл QFile, его содержимое передаю в QDomDocument::setContent(&file). Файл порядка 12 МБайт, парсится долго, иногда нужно прервать его парсинг. Но я так и не понял, как сделать корректно досрочное завершение потока.

Код:
#include <QThread>
#include <QDomDocument>
#include <QDomElement>

#include "railcore_global.h"

class RAILCORESHARED_EXPORT CDocReaderThread : public QThread
{
    Q_OBJECT

    QDomDocument    *   fdocument;
    QString             ffileName;

    Q_DISABLE_COPY(CDocReaderThread)

public:

    explicit CDocReaderThread(QDomDocument * document, const QString & fileName, QObject *parent = 0);
    void        run();

signals:

    void    done();
    void    error();

public slots:

};

Код:
#include <QFile>
#include "cdocreaderthread.h"

CDocReaderThread::CDocReaderThread(QDomDocument *document, const QString &fileName, QObject *parent) :
    QThread(parent),fdocument(document),ffileName(fileName)
{
}

void CDocReaderThread::run()
{
    if(!fdocument || ffileName.isEmpty())
    {
        emit    error();
    }
    else
    {
        QFile   file(ffileName);
        if(!file.open(QIODevice::ReadOnly))
        {
            emit    error();
            return;
        }

        QString errorMsg = "Unknown error";
        int     errorLine = -1;
        int     errorColumn = -1;

        if(!fdocument->setContent(&file,true,&errorMsg,&errorLine,&errorColumn))
        {
            qDebug("ArmDocument parse error: line %d, column %d: %s",errorLine,errorColumn,qPrintable(errorMsg));
            emit    error();
            return;
        }

        emit    done();
    }

Если делать так:
Код:
void abortRead()
{
reader->quit();
reader->wait();
}

То поток завершится после полного парсинга документа. и возвращается сигнал done().

Если пользоваться reader->terminate() то прога тупо виснет... Подскажите есть ли способ как то в процессе парсинга документа сделать завершение потока?


Название: Re: Прервать парсинг QDomDocument::setContent в отдельном потоке
Отправлено: kuzulis от Август 05, 2014, 18:19
Попробуй использовать QtConcurrent. Для прерывания там есть метод cancel(). Проверь, может заработает.


Название: Re: Прервать парсинг QDomDocument::setContent в отдельном потоке
Отправлено: alex312 от Август 05, 2014, 19:25
Попробуй использовать QtConcurrent. Для прерывания там есть метод cancel(). Проверь, может заработает.
cancel() не прерывает единичную функцию, чуда не происходит. Это действует если применять map() на массиве данных.


Название: Re: Прервать парсинг QDomDocument::setContent в отдельном потоке
Отправлено: Igors от Август 05, 2014, 19:37
Я бы попробовал унаследoваться от QFile и там ловить флажок отмены возвращая ошибку чтения.


Название: Re: Прервать парсинг QDomDocument::setContent в отдельном потоке
Отправлено: kuzulis от Август 05, 2014, 19:40
Цитировать
cancel() не прерывает единичную функцию, чуда не происходит. Это действует если применять map() на массиве данных.

А, ну тогда читать файл частями и на каждой итерации проверять некий флажок. И если он установлен в "break" - то не запускать следующую итерацию - а просто завершить (хотя не уверен что можно парсить DOM-документ по-частям).


Название: Re: Прервать парсинг QDomDocument::setContent в отдельном потоке
Отправлено: Fregloin от Август 05, 2014, 21:25
Да в том то и дело, что операция парсинга "атомарная" - даешь указатель на файл, и получаешь уже результат. :(
Оставил пока эту затею.


Название: Re: Прервать парсинг QDomDocument::setContent в отдельном потоке
Отправлено: m_ax от Август 05, 2014, 21:49
Да в том то и дело, что операция парсинга "атомарная" - даешь указатель на файл, и получаешь уже результат. :(
Оставил пока эту затею.
В этот процесс можно попытаться вклиниться)

Я бы попробовал унаследoваться от QFile и там ловить флажок отмены возвращая ошибку чтения.

Лучше отнаследоваться не от QFile, а от QXmlInputSource. Покурить там метод next.. Думаю, он его при парсинге дёргает, но это только предположение..
 


Название: Re: Прервать парсинг QDomDocument::setContent в отдельном потоке
Отправлено: Fregloin от Август 12, 2014, 15:46
я уже тоже об этом подумал, но пока забил.. есть куда более важные вещи.. )


Название: Re: Прервать парсинг QDomDocument::setContent в отдельном потоке
Отправлено: navrocky от Август 12, 2014, 16:42
Для больших документов лучше использовать QXmlStreamReader. Это поточный парсер и ты всегда можешь прервать разбор.