Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: akaMDA от Ноябрь 08, 2010, 16:05



Название: QList<MyTheard>
Отправлено: akaMDA от Ноябрь 08, 2010, 16:05
Необходимо сделать QList<MyTheard>. Каждый поток обрабатывает 1 текстовый файл из QStringList strLsFiles. При этом количество текстовых файлов и соответственно элементов-потоков в данном случае неизвестно заранее, а ввожится в процессе работы. Подскажите пожалуйста, каким отбразом можно организовать запуск этих потоков в цикле for. Делаю
Код:
for(int i=0; i<strLsFiles->count(); i++){
MyTheard[i].run(strLsFiles[i]);
}
Не работает(((
подскаже как быть!


Название: Re: QList<MyTheard>
Отправлено: UVV от Ноябрь 08, 2010, 16:55
MyThread::start()


Название: Re: QList<MyTheard>
Отправлено: akaMDA от Ноябрь 08, 2010, 16:59
Да, это я тут описался. Не работает.
Qobject is private


Название: Re: QList<MyTheard>
Отправлено: Пантер от Ноябрь 08, 2010, 17:12
Код MyTheard приведи.


Название: Re: QList<MyTheard>
Отправлено: akaMDA от Ноябрь 10, 2010, 15:49
Код:
/* 
 * File:   PreEdit.h
 * Author: akaMDA
 *
 * Created on 29 Октябрь 2010 г., 19:57
 */

#ifndef PREEDIT_H
#define PREEDIT_H

#include <QtCore/QtCore>

class PreEdit : public QThread {
    Q_OBJECT
public:
    PreEdit(QObject* parent, QString f);
    virtual ~PreEdit();
protected:
    void run();
private:
    QTextStream* ts_in;
    QTextStream* ts_out;
    QString file;
    QFile* file_in;
    QFile* file_out;
};

#endif /* PREEDIT_H */

/*
 * File:   PreEdit.cpp
 * Author: akaMDA
 *
 * Created on 29 Октябрь 2010 г., 19:57
 */

#include "PreEdit.h"

PreEdit::PreEdit(QObject* parent, QString f){
    setParent(parent);

    file= f;

    file_in = new QFile(file);
    file_in->open(QIODevice::ReadOnly);

    QString fil = file.split('\\').last();

    file_out = new  QFile(fil);
    file_out->open(QIODevice::WriteOnly);

    ts_in = new QTextStream(file_in);
    ts_in->setCodec("Windows-1251");

    ts_out = new QTextStream(file_out);
    ts_out->setCodec("Windows-1251");
}

PreEdit::~PreEdit() {
}

void PreEdit::run(){
    QChar ch;
    
    QChar pre_ch=0x0000;

    while(!ts_in->atEnd())
    {
        *ts_in>>ch;

        if(ch >= 0x0430 && ch <= 0x044F | ch >= 0x0061 && ch <= 0x007A | ch >= 0x0030 && ch <= 0x003A) *ts_out<<ch; //вставка без изменений маленьких букв, цифр

        if(ch == 0x0014 && pre_ch == 0x0014) continue; //удаление нескольких пробелов

        if(ch >= 0x0410 && ch <= 0x042F | ch >= 0x0041 && ch <= 0x005A) *ts_out<<(ch+32); //перевод в нижний регистр

        if(ch == 0x0401 | ch == 0x0451) *ts_out<<0x0435; // замена ёЁ на е

        if(ch == 0x002A || ch == 0x002B || ch == 0x002D || ch == 0x002F || ch == 0x003A || ch == 0x003C || ch == 0x003D || ch == 0x003E)//символы
        {
            if(pre_ch == ' ')
            {
                *ts_out<<0x0435;
                *ts_out<<' ';
                pre_ch = ' ';
                continue;
            }
            if(pre_ch != ' ')
            {
                *ts_out<<' ';
                *ts_out<<0x0435;
                *ts_out<<' ';
                pre_ch = ' ';
                continue;
            }
        }

        else continue;

        pre_ch=ch;
    }

    file_in->close();

    file_out->close();

    exec();
}


/*
 * File:   WizardPage2.h
 * Author: akaMDA
 *
 * Created on 29 Октябрь 2010 г., 9:52
 */

#ifndef WIZARDPAGE2_H
#define WIZARDPAGE2_H

#include <QtGui/QtGui>

class WizardPage2 : public QWizardPage {
    Q_OBJECT
public:
    WizardPage2(QWidget* parent);
    WizardPage2(QWidget* parent, const WizardPage2& orig);
    virtual ~WizardPage2();
    void setTextStat(QString* str);
    void begin();
private:
    QVBoxLayout* lay;
    QLabel* lbPict;
    QLabel* lbTextStat;
    QStringList* strLsFiles;
    void initializePage();
    //QList<PreEdit> lsPreEdit;
};

#endif /* WIZARDPAGE2_H */

/*
 * File:   WizardPage2.cpp
 * Author: akaMDA
 *
 * Created on 29 Октябрь 2010 г., 9:52
 */

#include "WizardPage2.h"
#include "PreEdit.h"

WizardPage2::WizardPage2(QWidget* parent) {
    setParent(parent);

    lay = new QVBoxLayout(this);

    lbPict = new QLabel(tr("Картинка часов"));
    lbPict->setAlignment(Qt::AlignCenter);
    lay->addWidget(lbPict, Qt::AlignCenter);

    lbTextStat = new QLabel(tr("Состояние процесса"));
    lbTextStat->setAlignment(Qt::AlignCenter);
    lay->addWidget(lbTextStat, Qt::AlignCenter);

    strLsFiles = new  QStringList;

    setLayout(lay);
}

WizardPage2::WizardPage2(QWidget* parent, const WizardPage2& orig) {
}

WizardPage2::~WizardPage2() {
}

void WizardPage2::setTextStat(QString* str){
    lbTextStat->setText(*str);
}

void  WizardPage2::initializePage(){
     strLsFiles->append(field("File").toStringList());
     begin();
}

void WizardPage2::begin(){
    PreEdit pe(this, strLsFiles->at(0));
    pe.start(QThread::IdlePriority);
}


Компилится и собирается нормально, но при запуске происходит ошибка:
Прпкращена работа
Сигнатура проблемы:
  Имя события проблемы:   APPCRASH
  Имя приложения:   DataClustering.exe
  Версия приложения:   0.0.0.0
  Отметка времени приложения:   4cda94ab
  Имя модуля с ошибкой:   QtCored4.dll
  Версия модуля с ошибкой:   4.7.0.0
  Отметка времени модуля с ошибкой:   4c8d7577
  Код исключения:   c0000005
  Смещение исключения:   001aea99
  Версия ОС:   6.1.7600.2.0.0.768.11
  Код языка:   1049
  Дополнительные сведения 1:   0a9e
  Дополнительные сведения 2:   0a9e372d3b4ad19135b953a78882e789
  Дополнительные сведения 3:   0a9e
  Дополнительные сведения 4:   0a9e372d3b4ad19135b953a78882e789

Ознакомьтесь с заявлением о конфиденциальности в Интернете:
  http://go.microsoft.com/fwlink/?linkid=104288&clcid=0x0419

Если заявление о конфиденциальности в Интернете недоступно, ознакомьтесь с его локальным вариантом:
  C:\windows\system32\ru-RU\erofflps.txt


Название: Re: QList<MyTheard>
Отправлено: akaMDA от Ноябрь 10, 2010, 15:51
В приведенном коде пытаюсь даже не весь список обработать, а только хотя бы первый файл...


Название: Re: QList<MyTheard>
Отправлено: Пантер от Ноябрь 10, 2010, 15:54
На какой из этих строк падает?
PreEdit pe(this, strLsFiles->at(0));
pe.start(QThread::IdlePriority);


Название: Re: QList<MyTheard>
Отправлено: UVV от Ноябрь 10, 2010, 17:00
И правильно делает, что падает, поскольку объект PreEdit должен быть членом класса.
А так, как у тебя сейчас, оно просто уходит за пределы видимости.


Название: Re: QList<MyTheard>
Отправлено: akaMDA от Ноябрь 10, 2010, 22:34
Да, все заработало.
Считывает отлично, но выводит в файл только при QThread::HighestPriority!!!
О_О

Это с чем связано?


Название: Re: QList<MyTheard>
Отправлено: UVV от Ноябрь 10, 2010, 23:36
А чего ты хотел добиться, указав QThread::IdlePriority?
Ты вообще assistant читал по этому поводу?
Не указывай никаких параметров просто.


Название: Re: QList<MyTheard>
Отправлено: akaMDA от Ноябрь 10, 2010, 23:46
Вообще вот хотел спросить. Пишу щас дипломную работу по теме "Разработка программного комплекса класстеризации текстовой информации на основе нейронных сетей". Естественно в программе есть несколько независимых мест, выполнение которых можно распаралелить. Это например работа каждого нейрона, векторизация текста (это и есть его начало) и т.д. Так имеет ли смысл это превращать в отдельные потоки? Или в данном случае это бессмысленно?


Название: Re: QList<MyTheard>
Отправлено: UVV от Ноябрь 10, 2010, 23:54
Про нейронные сети ничего не подскажу (не моя специализация), но распараллеливание на потоки может дать существенный прирост в производительности, когда оно правильно применено. В Qt есть несколько способов распараллелить задачу, потоки - не единственный.


Название: Re: QList<MyTheard>
Отправлено: akaMDA от Ноябрь 11, 2010, 00:05
А какие еще способы в Qt есть?

просто я этой проблемой еще не сталкивался. Вот если все последовательно делать, то корость обработки 1 текста получется выше, чем если распараллелить. Прирост в скорости существенный я думаю будет уже при очень большом количестве входных текстов. А процессы даже QThread::HighestPriority, иногда вообще выпиливаются системой. Так например у меня получилось в какой-то момент времени, что 3 строчки просто перенос без разбора, комп 2 мин делал! Может есть способ в Qt сделать так, чтоб выполняемая задача была на критическом пути у системы и ее ничего не прерывало?


Название: Re: QList<MyTheard>
Отправлено: UVV от Ноябрь 11, 2010, 00:08
QtConcurrent


Название: Re: QList<MyTheard>
Отправлено: BlackTass от Ноябрь 11, 2010, 01:03
Конкаррент не поможет, там те же самые потоки, только обернутые в более простой синтаксис.

Чтобы ничего не прерывало средств не бывает. Пользуйтесь rtos, там возможностей в этом плане побольше.


Название: Re: QList<MyTheard>
Отправлено: akaMDA от Ноябрь 11, 2010, 15:06
а KDE есть на qnx?


Название: Re: QList<MyTheard>
Отправлено: BlackTass от Ноябрь 11, 2010, 20:51
Не слышал честно говоря) и не очень уверен что вам нужно оно. Задача не настолько критичная ко времени, чтобы идти на такие меры. Есть подозрение, что у вас проблемы с производительностью из-за самого подхода. Если расскажете поподробнее алгоритм и как вы пытаетесь его распараллелить, то может я или кто другой подскажет как лучше сделать, чтобы работало и на обычных ос


Название: Re: QList<MyTheard>
Отправлено: akaMDA от Ноябрь 13, 2010, 13:27
Да вроде добился уже, что работает.
Но возникла проблема - если 1 поток и чен класса, то работает нормально. При использовании же QList начинает падать, т.к. элементы уходят из зоны видимости. Как ркшить эту проблему?


Название: Re: QList<MyTheard>
Отправлено: BlackTass от Ноябрь 14, 2010, 13:51
Может стоит привести немного кода, чтобы было понятнее о чем вопрос?


Название: Re: QList<MyTheard>
Отправлено: akaMDA от Ноябрь 14, 2010, 20:03
Код:
    for(int i = 0; i < strLsFiles.count(); ++i)
    {
        ltVT[i].init(this, strLsFiles.at(i));
        ltVT[i].start(QThread::TimeCriticalPriority);

    }

вот код))
сложность в том, что нада запускать этот цикл не в конструкторе виджета. т.е. конструктор QList запускается раньше.
При старт поток падает.


Название: Re: QList<MyTheard>
Отправлено: BlackTass от Ноябрь 15, 2010, 01:09
Я так понимаю strLsFiles это некая локальная переменная, которая заполняется объектами (не указателями на них)? Покажите заполнение strLsFiles и метод init()


Название: Re: QList<MyTheard>
Отправлено: akaMDA от Ноябрь 15, 2010, 15:25
QStringList strLsFiles - это член-данная класса, в которм запускаются потоки. В ней хранятся адреса текстовых файлов. Но к данной проблеме она отношения не имеет. если объявить несколько объктов не в QList - то работает отлично. Если же объявлять их в  QList - падают при запуске метода  start. Аналогично,если объект класса-потока объявить в функции. Следовательно при инициализации в  QList его элементы выходят за область видимости. Не могу пока решить эту проблему.

Код:
#ifndef VECTORINGTEXT_H
#define VECTORINGTEXT_H

#include "QtCore/QtCore"

class VectoringText : public QThread
{
public:
    VectoringText(QObject* parent = 0, QString str = "");
    VectoringText(const VectoringText& vt);
    virtual ~VectoringText();
    bool operator =(const VectoringText& vt);
    void init(QObject* parent = 0, QString str = "");
protected:
    void run();
private:
    QString fil_in;
    QString fil_out;
};

#endif // VECTORINGTEXT_H


#include "vectoringtext.h"

VectoringText::VectoringText(QObject* parent, QString str)
{
    setParent(parent);

    fil_in = str;

    fil_out = fil_in+"_CL.txt";
}

VectoringText::VectoringText(const VectoringText& vt)
{
    setParent(vt.parent());

    fil_in = vt.fil_in;

    fil_out = vt.fil_out;
}

VectoringText::~VectoringText()
{
}

bool VectoringText::operator =(const VectoringText& vt)
{
    setParent(vt.parent());

    fil_in = vt.fil_in;

    fil_out = vt.fil_out;

    return true;
}

void VectoringText::init(QObject* parent, QString str)
{
    setParent(parent);

    fil_in = str;

    fil_out = fil_in+"_CL.txt";
}

void VectoringText::run()
{
    QFile file_in(fil_in);
    if(!file_in.open(QIODevice::ReadOnly)) return;

    QFile file_out(fil_out);
    if (!file_out.open(QIODevice::WriteOnly)) return;

    QTextStream in(&file_in);

    QTextStream out(&file_out);

    char ch = ' ';

    char pre_ch = ' ';

    while (!in.atEnd())
    {
        in>>ch;

        out<<ch;

        pre_ch = ch;
    }

    file_in.close();

    file_out.close();

    exec();
}



/*
 * File:   WizardPage2.h
 * Author: akaMDA
 *
 * Created on 29 ������� 2010 �., 9:52
 */

#ifndef WIZARDPAGE2_H
#define WIZARDPAGE2_H

#include <QtGui/QtGui>
#include "vectoringtext.h"

class WizardPage2 : public QWizardPage {
    Q_OBJECT
public:
    WizardPage2(QWidget* parent);
    WizardPage2(QWidget* parent, const WizardPage2& orig);
    virtual ~WizardPage2();
    void setTextStat(QString str);
    void begin();
private:
    QVBoxLayout* lay;
    QLabel* lbPict;
    QLabel* lbTextStat;
    QStringList strLsFiles;
    void initializePage();
    QList<VectoringText> ltVT;
    VectoringText vt;
    QStack<bool> stack_thread;
};

#endif /* WIZARDPAGE2_H */




/*
 * File:   WizardPage2.cpp
 * Author: akaMDA
 *
 * Created on 29 Октябрь 2010 г., 9:52
 */

#include "WizardPage2.h"

WizardPage2::WizardPage2(QWidget* parent) {
    setParent(parent);

    lay = new QVBoxLayout(this);

    lbPict = new QLabel(tr("Картинка часов"));
    lbPict->setAlignment(Qt::AlignCenter);
    lay->addWidget(lbPict, Qt::AlignCenter);

    lbTextStat = new QLabel(tr("Состояние процесса"));
    lbTextStat->setAlignment(Qt::AlignCenter);
    lay->addWidget(lbTextStat, Qt::AlignCenter);

    setLayout(lay);
}

WizardPage2::WizardPage2(QWidget* parent, const WizardPage2& orig) {
}

WizardPage2::~WizardPage2() {
}

void WizardPage2::setTextStat(QString str)
{
    lbTextStat->setText(str);
}

void  WizardPage2::initializePage()
{
     strLsFiles.append(field("File").toStringList());

     setTextStat(tr("Инициализация..."));

     begin();
}

void WizardPage2::begin()
{
    setTextStat(tr("Векторизация текста"));

    vt.init(this, strLsFiles.at(0));
    vt.start(QThread::TimeCriticalPriority);
    for(int i = 0; i < strLsFiles.count(); ++i)
    {
        ltVT[i](this, strLsFiles.at(i));
        ltVT[i].start(QThread::TimeCriticalPriority);

        stack_thread.push(1);
    }

    setTextStat(tr("Окончание"));
}


при вызове старт возникает ошибка -
Сигнатура проблемы:
  Имя события проблемы:   APPCRASH
  Имя приложения:   DataClustering.exe
  Версия приложения:   0.0.0.0
  Отметка времени приложения:   4ce12697
  Имя модуля с ошибкой:   QtCored4.dll
  Версия модуля с ошибкой:   4.7.0.0
  Отметка времени модуля с ошибкой:   4c8d7577
  Код исключения:   40000015
  Смещение исключения:   0000e680
  Версия ОС:   6.1.7600.2.0.0.768.11
  Код языка:   1049
  Дополнительные сведения 1:   0c46
  Дополнительные сведения 2:   0c468683048b9b6a0bbe53bf3a1fd8b9
  Дополнительные сведения 3:   d6d5
  Дополнительные сведения 4:   d6d507d9b5ddac7e52e2d5f5e0bb6da2

Ознакомьтесь с заявлением о конфиденциальности в Интернете:
  http://go.microsoft.com/fwlink/?linkid=104288&clcid=0x0419

Если заявление о конфиденциальности в Интернете недоступно, ознакомьтесь с его локальным вариантом:
  C:\windows\system32\ru-RU\erofflps.txt


Название: Re: QList<MyTheard>
Отправлено: BlackTass от Ноябрь 15, 2010, 22:47
Ок, а если в дебаге глянуть где падает? Так вроде на первый взгляд ничего криминального нет.


Название: Re: QList<MyTheard>
Отправлено: akaMDA от Ноябрь 15, 2010, 23:05
Так смотрел. Падает на start(). Видимо выходит за область видимости. Видимо объекты QList не становятся членами класса...


Название: Re: QList<MyTheard>
Отправлено: BRE от Ноябрь 15, 2010, 23:17
Код
C++ (Qt)
void WizardPage2::begin()
{
   ...
   for(int i = 0; i < strLsFiles.count(); ++i)
   {
       ltVT[i](this, strLsFiles.at(i)); // ???
       ltVT[i].start(QThread::TimeCriticalPriority);
 
       stack_thread.push(1);
   }
   ...
}
 

Список ltVT изначально вроде пуст, в него ничего не добавляли, а ты по индексу обращаешься к элементам которых нет.
Копировать объекты QObject (и их наследников) нельзя, тем более так как делаешь ты в конструкторе копирования/операторе=.


Название: Re: QList<MyTheard>
Отправлено: akaMDA от Ноябрь 15, 2010, 23:22
Ммм, а как иницировать эти элементы тогда. Сначала пробовал запустить контструктор - но не дает


Название: Re: QList<MyTheard>
Отправлено: BRE от Ноябрь 15, 2010, 23:41
Ммм, а как иницировать эти элементы тогда. Сначала пробовал запустить контструктор - но не дает
Т.к. копировать объекты классов наследников QObject нельзя, то придется использовать указатели.
Код
C++ (Qt)
class WizardPage2 : public QWizardPage {
   ...    
   QList<VectoringText*> ltVT;
};
 
   ...
 
   for(int i = 0; i < strLsFiles.count(); ++i)
   {
VectoringText *task = new VectoringText( strLsFiles[ i ] );
ltVT.append( task );
task->start();
   }
 


Название: Re: QList<MyTheard>
Отправлено: akaMDA от Ноябрь 16, 2010, 15:18
Код:
 for(int i = 0; i < strLsFiles.count(); ++i)
    {
       VectoringText *vt = new VectoringText(this, strLsFiles[i]);

       ltVT.append(vt);
       ltVT[i]->start(QThread::TimeCriticalPriority);
    }

Во, вот так только)) Спасибо, заработало))