crossplatform.ru

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

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> Приостановка потока
AD
  опции профиля:
сообщение 4.6.2009, 16:49
Сообщение #1


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

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

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




Репутация:   17  


Не понимаю, почему нет паузы в выполнении. Делаю так:
connect(btnPauseVertical, SIGNAL(clicked()), this, SLOT(pauseVerticalCycles()));
/// Приостановка выполнения процесса перемещения в вертикальной проекции (или запуск с места остановки)
void AutoControl::pauseVerticalCycles()
{
    if(btnPauseVertical -> isChecked())
    {
        bool p = vertical -> wait();
        int u = 0;
    }
    /*else
        vertical -> start();*/
}

В чем недочеты? Почему не удается приостановить выполнение функции run()?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 4.6.2009, 17:35
Сообщение #2


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

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

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




Репутация:   44  


Цитата(AD @ 4.6.2009, 17:49) *
Не понимаю, почему нет паузы в выполнении. Делаю так:
В чем недочеты? Почему не удается приостановить выполнение функции run()?

Потому, что QThread::wait ждет момента завершения нити или наступления таймаута и выходит. Она нить не приостанавливает!

Сообщение отредактировал BRE - 4.6.2009, 17:35
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 4.6.2009, 17:37
Сообщение #3


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

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

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




Репутация:   17  


Тогда вопрос: как заставить его таймаутиться?

Даже точнее: приостанавливать выполнение run(), а потом запускать run() с места остановки?

Сообщение отредактировал AD - 4.6.2009, 17:39
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 4.6.2009, 18:02
Сообщение #4


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

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

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




Репутация:   44  


Цитата(AD @ 4.6.2009, 18:37) *
Тогда вопрос: как заставить его таймаутиться?

Даже точнее: приостанавливать выполнение run(), а потом запускать run() с места остановки?

Циклы, флаги внутри run.
Посмотри на prog.org, там обсуждалась подобная тема: http://www.prog.org.ru/topic_8910_0.html
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 4.6.2009, 19:06
Сообщение #5


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

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

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




Репутация:   17  


Ну.... мне удалось сделать такую фишку! :)

Вот таким образом:
/// Класс потока - вращение вокруг горизонтальной оси заданное количество раз
class VerticalRotation: public QThread
{
    Q_OBJECT

private:
    int cur_num_cycle;                            ///< текущее номер цикла
    bool terminated;                            ///< флаг сигнализации о том, что функцию run надо прервать

private:
    void cycleRotate();

protected:
    virtual void run();

signals:
    void valueDecrement(int);
    void timeout(int);

private slots:
    void terminateCycle(int index);

public:
    void setNumberCycle(int index) { cur_num_cycle = index; }
    int currentNumber() const { return cur_num_cycle; }
    void setTerminate(bool bf) { terminated = bf; }
    bool isTeminated() const { return terminated; }
};

/// в конструкторе
connect(this, SIGNAL(timeout(int)), SLOT(terminateCycle(int)));

/// Прерывание цикла
void VerticalRotation::terminateCycle(int index)
{
    cur_num_cycle = index;
    terminated = true;
}

/// Выполнение цикла перемещений прожектора
void VerticalRotation::cycleRotate()
{
    int geted_angle_elev = VALFROMBYTES(inf_from_ed_packet.high_angle_elev, inf_from_ed_packet.low_angle_elev);
    readAngleElevation(geted_angle_elev, 10.);

    const int number_cycles = number_rotate;
    for(register int i=cur_num_cycle; i<number_cycles && !terminated; ++i)
    {
        int angle_elevation = -110 * 10;
        inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation);
        inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation);
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
        readAngleElevation(geted_angle_elev, -110.);

        angle_elevation = 10 * 10;
        inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation);
        inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation);
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
        readAngleElevation(geted_angle_elev, 10.);
        --number_rotate;
        emit valueDecrement(number_rotate);
        emit timeout(i);
    }
}

/// Запуск потока вращения в вертикальной плоскости
void VerticalRotation::run()
{
    if(!number_rotate) return;
    if(terminated) return;

    int geted_angle_elev = VALFROMBYTES(inf_from_ed_packet.high_angle_elev, inf_from_ed_packet.low_angle_elev);
    int angle_elevation = 10 * 10;                        ///< верхний предел прожектора
    if(geted_angle_elev < ((10. - 1.5) * 10) || geted_angle_elev > ((10. + 1.5) * 10))
    {
        inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation);
        inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation);
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
    }

    /// внешний цикл по количеству перемещений
    cycleRotate();

    if(!number_rotate) { terminated = false; quit(); }
}



connect(vertical, SIGNAL(timeout(int)), SLOT(pauseVerticalCycles()));
/// Приостановка выполнения процесса перемещения в вертикальной проекции (или запуск с места остановки)
void AutoControl::pauseVerticalCycles()
{
    if(btnPauseVertical -> isChecked()) vertical -> setTerminate(true);
    else { vertical -> setTerminate(false); vertical -> start(); }
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 5.6.2009, 0:52
Сообщение #6


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

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

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




Репутация:   29  


AD, мне всегда нравились твои краткие примеры ;)

То что ты cделал противоречит тобою же поставленной задачей.
Цитата(AD)
приостанавливать выполнение run(), а потом запускать run() с места остановки?

То, что ты делаешь, это называется завершение потока
Цитата
if(terminated) return;

А в дальнейшем, ты создаешь его заново
Цитата
vertical -> start();
т.е выполнение начнется с первой строки метода run.

В строке
if(!number_rotate) { terminated = false; quit(); }
quit убери, он тут ни к чему. Поток и так завершится.

Если ты реально хочешь приостановиь поток, а потом продолжить с места остановки, используй QMutex совместно с QWaitCondition. Да и в принципе мьютексами пользоваться не стесняйся ;)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 5.6.2009, 10:03
Сообщение #7


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

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

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




Репутация:   17  


Цитата(igor_bogomolov @ 5.6.2009, 1:52) *
Если ты реально хочешь приостановиь поток, а потом продолжить с места остановки, используй QMutex совместно с QWaitCondition. Да и в принципе мьютексами пользоваться не стесняйся ;)

Если бы знал, как корректно ими воспользоваться - обязательно бы это сделал! ;) :) Подскажешь, буду благодарен! :)

А вообще, да, я запускаю run с первой строчки, но:
1) у меня цикл начинается с места остановки;
2) условие, которое проверяется перед циклом, не выполняется, потому что прожектор и так, в крайнем верхнем положении!

P.S.
Подкорректировал код:
private slots:
void terminateCycle(int index) { terminated = true; }

/// Выполнение цикла перемещений прожектора
void VerticalRotation::cycleRotate()
{
    int geted_angle_elev = VALFROMBYTES(inf_from_ed_packet.high_angle_elev, inf_from_ed_packet.low_angle_elev);
    readAngleElevation(geted_angle_elev, 10.);

    const int number_cycles = number_rotate;
    for(register int i=0; i<number_cycles && !terminated; i++)
    {
        int angle_elevation = -110 * 10;
        inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation);
        inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation);
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
        readAngleElevation(geted_angle_elev, -110.);

        angle_elevation = 10 * 10;
        inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation);
        inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation);
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
        readAngleElevation(geted_angle_elev, 10.);
        --number_rotate;
        emit valueDecrement(number_rotate);
        if(checked_pause) emit timeout(i);
    }
}

/// Запуск потока вращения в вертикальной плоскости
void VerticalRotation::run()
{
    if(!number_rotate) return;
    if(terminated) return;

    int geted_angle_elev = VALFROMBYTES(inf_from_ed_packet.high_angle_elev, inf_from_ed_packet.low_angle_elev);
    int angle_elevation = 10 * 10;                        ///< верхний предел прожектора
    if(geted_angle_elev < ((10. - 1.5) * 10) || geted_angle_elev > ((10. + 1.5) * 10))
    {
        inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation);
        inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation);
        if(imitTsl) imitTsl -> writeFromCtrlAutoPage();
    }

    /// внешний цикл по количеству перемещений
    cycleRotate();

    if(!number_rotate) { checked_pause = false; terminated = false; quit(); }
}


/// Приостановка выполнения процесса перемещения в вертикальной проекции (или запуск с места остановки)
void AutoControl::pauseVerticalCycles()
{
    if(btnPauseVertical -> isChecked())
    {
        vertical -> setChecked(true);
        vertical -> setTerminate(true);
        btnPauseVertical -> setFlat(true);
    }
    else
    {
        vertical -> setChecked(false);
        vertical -> setTerminate(false);
        vertical -> start();
        btnPauseVertical -> setFlat(false);
    }
}


Сообщение отредактировал AD - 5.6.2009, 10:03
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.6.2009, 10:06
Сообщение #8


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

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




Репутация:   94  


AD, сворачивай код, слишком длинный
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 5.6.2009, 10:24
Сообщение #9


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

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

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




Репутация:   29  


Цитата(AD @ 5.6.2009, 11:03) *
2) условие, которое проверяется перед циклом, не выполняется, потому что прожектор и так, в крайнем верхнем положении!
Ну тогда убери строку раз она не нужна. А то этот quit в конце потока, как то глаз немного режет. Не нужет он там. Да и вообще, использование quit внутри run, выглядит как то странно.

Цитата(AD @ 5.6.2009, 11:03) *
1) у меня цикл начинается с места остановки;
Это другой вопрос. Что у тебя там происходит реально, разобраться даже и не пытался. Если все переменные сохраняются, и при новом запуске потока, все выглядит так, как будто ты продолжил с точки остонава, то можешь оставить и так. Это тоже вариант. Но только это не универсальное решение. Будешь решать другую задачу, опять сталкнешся с трудностями. Так что с мьютексами все равно надо разбираться. Тем более, что поток у тебя не безопасный. ИМХО.

Цитата(AD @ 5.6.2009, 11:03) *
Если бы знал, как корректно ими воспользоваться - обязательно бы это сделал!
Попробую небольшой тестовый пример накатать. :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 5.6.2009, 10:29
Сообщение #10


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

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

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




Репутация:   17  


Цитата(igor_bogomolov @ 5.6.2009, 11:24) *
Ну тогда убери строку раз она не нужна. А то этот quit в конце потока, как то глаз немного режет. Не нужет он там. Да и вообще, использование quit внутри run, выглядит как то странно.

Вот то что не пытался разобраться - это плохо! Я даже прокомментировал все действия. что выполняются в этих функциях!
А убрать - не уберу, потому что это условие не выполняется, когда туда заходим после паузы, а при первом заходе, как правило, оно срабатывает. Так и должно быть! А вообще был очень удивлен, что я впринципе могу работать с одной структурой в двух разных потоках. Убедился, что это так - единственное, разные поля этой структуры обрабатываются разными потоками!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

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


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




RSS Текстовая версия Сейчас: 3.1.2025, 7:50