crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

> Проблема с правильным завершением дополнительного потока
AD
  опции профиля:
сообщение 12.9.2008, 10:06
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Я не понимаю, почему у меня нет корректного завершения потока. Заходит в поток только при первом вызове, а соответственно рисует график только при первом выборе параметров, далее необходимо закрывать это диалоговое окошко и открывать снова- что крайне неудобно. Просьба, пожалуйста, поясните, в чем ошибки?
Ниже приведен код:
thread

class GraphicDisplay : public QDialog, public Ui::GraphicDisplayClass
{
    Q_OBJECT

private:
    QMap<int, QVector<QPointF>> curveMap;       ///< список всех изображаемых кривых
    // куча переменных

private:
    void drawGrid(QPainter* painter);
    void drawCurves(QPainter* painter);
    void drawLegend(QPainter* painter, QRect& rect, int& k, int id);
    QPointF initXY(double& sx, double& sy);
    QPointF initXY(const QPoint* scr_coor);

protected:
    void paintEvent(QPaintEvent* events);
    void keyPressEvent(QKeyEvent* events);
    void wheelEvent(QWheelEvent* events);
    void mousePressEvent(QMouseEvent* events);
    void mouseMoveEvent(QMouseEvent* events);
    void mouseReleaseEvent(QMouseEvent* events);
    void contextMenuEvent(QContextMenuEvent* events);
    void resizeEvent(QResizeEvent* events) { QDialog::resizeEvent(events); update(); }
    void closeEvent(QCloseEvent* events) { QDialog::closeEvent(events); }
    void showEvent(QShowEvent* events) { QDialog::showEvent(events); }

public:
    GraphicDisplay(QWidget *parent = 0);
    GraphicDisplay(QWidget *parent, ParamPlotSettings& st);
    ~GraphicDisplay();
    // куча функций
    void initThread(QDialDistParam* pD, QDialTimeParam* pT, PlotSettings* sts);
                void fillCurve();
};

/// Инициализация нужных для потока параметров
void GraphicDisplay::initThread(QDialDistParam* pD, QDialTimeParam* pT, PlotSettings* sts)
{
    p_thread -> mainWindow = mainWindow;
    p_thread -> pDist = pD;
    p_thread -> pTime = pT;
    p_thread -> settings = sts;
    p_thread -> CurveMap(&curveMap);
}

/// Заполнение вектора данными
void GraphicDisplay::fillCurve()
{
    curveMap.clear();
    p_thread -> start();
    if(p_thread -> getStop())
        p_thread -> stop();

    update();
}


/// Класс параллельного потока для заполнения данными кривых графика
class DTThread: public QThread
{
    Q_OBJECT

private:
    QMap<int, QVector<QPointF>>* curveMap;      ///< список изображаемых кривых
    volatile bool stopped;                        ///< переменная, контролирующая начало и конец выполнения потока
    QMutex mtx;                                    ///< мьютекс для блокировки данных при работе с дополнительным потоком

public:
    QPen myPen;                                    ///< карандаш для рисования линий определенной жирности и цвета
    TLV* mainWindow;                            ///< указатель на главное окно
    QVector<QPointF> data;                        ///< вектор загружаемой кривой
    QDialDistParam* pDist;                        ///< указатель на класс диалога параметров по расстоянию
    QDialTimeParam* pTime;                        ///< указатель на класс диалога параметров по времени
    PlotSettings* settings;                        ///< указатель на настройку для определения масштаба

private:
    void fillXVec(QVector<QPointF>& data);

protected:
    void run();

public:
    DTThread(): stopped(false), pDist(0), pTime(0), mainWindow(0) {}
    ~DTThread() { mtx.lock(); stopped = true; mtx.unlock(); }
    void stop() { mtx.lock(); stopped = true; mtx.unlock(); quit(); };
    QMap<int, QVector<QPointF>>* CurveMap() { return curveMap; }
    void CurveMap(QMap<int, QVector<QPointF>>* crv) { mtx.lock();  curveMap = crv; mtx.unlock(); }
    bool getStop() { return stopped; }
};

/// Запуск дополнительного потока
void DTThread::run()
{
    if(!stopped)
    {
        int id = 0;
        /// Заполнение данными по оси x
        fillXVec(data);

        for(fact_param_iter fit=fact_prm.begin(); fit!=fact_prm.end(); ++fit, ++id)
        {
            /// Заполнение данными по оси y
            ParamDescr* param_record = fit -> param_record;
            int index = 0;
            for(logI jter=mainWindow -> log.begin(); jter!=mainWindow -> log.end() && index!=data.size(); ++jter, ++index)
            {
                PARAMVALUE val = jter -> GetParamValue(&mainWindow -> cur_rec, param_record -> Name(),
                                                    param_record -> Address());
                data[index].setY(val.value);
            }
            curveMap -> insert(id, data);
        }
        mtx.lock(); stopped = true; mtx.unlock();
    }

    exec();
}

/// Заполнение данными по оси x
void DTThread::fillXVec(QVector<QPointF>& data)
{
    double x = 0.0;
    ParamPlotSettings* p_set = (ParamPlotSettings*)settings;
    switch(p_set -> win_type)
    {
    case DISTPARAM:
        for(QVector<PARAMVALUE>::iterator iter=x_data.dist_x.begin(); iter!=x_data.dist_x.end(); ++iter)
        {
            x += (iter -> value / 1000.0);
            data.push_back(QPointF(x, 0.0));
            int k = 0;
            switch(iter -> status)
            {
            case PS_FAIL:
                k = pDist -> spinFault -> text().toInt();
                myPen.setWidth(k);
            break;
            case PS_NODATA:
                k = pDist -> spinNoData -> text().toInt();
                myPen.setWidth(k);
            break;
            case PS_TEST:
                k = pDist -> spinTest -> text().toInt();
                myPen.setWidth(k);
            break;
            case PS_OK:
                k = pDist -> spinNormal -> text().toInt();
                myPen.setWidth(k);
            break;
            }
        }
    break;
    case TIMEPARAM:
        for(QVector<PARAMVALUE>::iterator iter=x_data.time_x.begin(); iter!=x_data.time_x.end(); ++iter)
        {
            x += (iter -> value / 60.0);
            data.push_back(QPointF(x, 0.0));
            int k = 0;
            switch(iter -> status)
            {
            case PS_FAIL:
                k = pTime -> spinFault -> text().toInt();
                myPen.setWidth(k);
            break;
            case PS_NODATA:
                k = pTime -> spinNoData -> text().toInt();
                myPen.setWidth(k);
            break;
            case PS_TEST:
                k = pTime -> spinTest -> text().toInt();
                myPen.setWidth(k);
            break;
            case PS_OK:
                k = pTime -> spinNormal -> text().toInt();
                myPen.setWidth(k);
            break;
            }
        }
    break;
    }
}



Заранее благодарен за помощь!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
 
Начать новую тему
Ответов
Tonal
  опции профиля:
сообщение 12.9.2008, 11:29
Сообщение #2


Активный участник
***

Группа: Участник
Сообщений: 452
Регистрация: 6.12.2007
Из: Новосибирск
Пользователь №: 34

Спасибо сказали: 69 раз(а)




Репутация:   17  


Переходи на 4.4? :)

А набросок примерно такой:
QWaitCondition w_terminated;
QMutex m_terminated;
QReadWriteLock rw_run;
void DTThread::Run() {
  while(!w_terminated.wait(m_terminated, 0)) {
    QWriteLocker w_run(rw_run);
    //Здесь выполняем то, что у тебя было внутри if(!stopped)
  }
}

/// Инициализация нужных для потока параметров
void GraphicDisplay::initThread(QDialDistParam* pD, QDialTimeParam* pT, PlotSettings* sts) {
  //Здесь старая инициализация
    w_run.lockForRead();
    p_thread -> start();
}

/// Заполнение вектора данными
void GraphicDisplay::fillCurve() {
    curveMap.clear();
    w_run.unlock();
    w_run.lockForRead();
    update();
}

Ну и в конце приложения нужно w_terminated.wakeAll() сделать.
Только смысла в этом всём нет, т.к. у тебя получается, что главный поток просто замерзает и ждёт окончания рабочего.
Чтобы не замерзал, нужно fillCurve разбить ровно на 2 половины: 1 - начать пересчёт, 2 - проверить не посчиталось ли (tryLockForRead), и если посчиталось - обновится. :)
Ну и данные и потока и главного окна должны быть разные в этом случае.

Сообщение отредактировал Tonal - 12.9.2008, 11:29
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Сообщений в этой теме
- AD   Проблема с правильным завершением дополнительного потока   12.9.2008, 10:06
- - ЙаМайскЫйПчОЛ   Удалено   12.9.2008, 10:24
- - Tonal   Всё правильно - так и должно быть (в смысле выполн...   12.9.2008, 10:32
|- - AD   Цитата(Tonal)Всё правильно - так и должно быть (в ...   12.9.2008, 10:51
- - Tonal   Переходи на 4.4? А набросок примерно такой: QWai...   12.9.2008, 11:29
|- - AD   Цитата(Tonal @ 12.9.2008, 12:29) Переходи...   12.9.2008, 11:40
- - Tonal   Я же написал, что нужно изменить - fillCurve() раз...   12.9.2008, 12:03
|- - AD   Ну и последний вопросик: А набросок примерно такой...   12.9.2008, 12:20
|- - AD   Видимо, где-то напортачил, но вот где? Ломается с ...   12.9.2008, 13:26
- - trdm   Цитата(Tonal @ 12.9.2008, 13:03) Причём э...   12.9.2008, 13:39
|- - AD   Немного изменил. Все-равно ломается, во-первых, пр...   12.9.2008, 16:52
|- - AD   Поправил немного. Но все-равно, работает кривовато...   15.9.2008, 11:14
- - Tonal   Извини, правда некогда разбираться. Но, если ты т...   19.9.2008, 10:11
- - AD   Не знаю уж чего я там еще такого наваял, но пока в...   19.9.2008, 11:01


Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 27.4.2024, 14:32