crossplatform.ru

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

3 страниц V  < 1 2 3 >  
Ответить в данную темуНачать новую тему
> [РЕШЕНО] Работа таймеров в параллельном потоке
BRE
  опции профиля:
сообщение 30.11.2009, 17:29
Сообщение #11


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

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

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




Репутация:   44  


Цитата(AD @ 30.11.2009, 17:27) *
А я правильно понимаю, что это таймер заканчивает свое действие, как только программа выходит из функции run()?

Да, и при этом таймер сам разрушиться.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 30.11.2009, 17:38
Сообщение #12


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

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

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




Репутация:   17  


Блин. Я убрал строку остановки таймера, но в слот все-равно программа не заходит... Что еще может быть не так?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 30.11.2009, 17:46
Сообщение #13


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

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

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




Репутация:   44  


Попробуй такой код:
void ContinueRotation::run()
{
    QTimer timerReading;
    connect(&timerReading,  SIGNAL(timeout()), this, SLOT(reading()));
    timerReading.start(1000);
    exec();
}

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 30.11.2009, 18:01
Сообщение #14


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

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

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




Репутация:   17  


Не попадает....

Так.... попало. Интересно, а такой код приемлем?
/// Запуск потока вращения в обеих плоскостях длительный промежуток времени
void ContinueRotation::run()
{
    connect(imitTsl, SIGNAL(continue_stop()), SLOT(exit()));
    connect(this, SIGNAL(working_light()), SLOT(workSpotlight()));

    QTimer timerReading;
    connect(&timerReading,  SIGNAL(timeout()), this, SLOT(reading()));
    timerReading.start(1000);
    exec();

    for(int timer_count=0; QTime::currentTime()<=finished_time;)
    {
        if(_finished) break;
        timerTicks();
        if(timer_count == 60) timer_count = 0;
        if(!timer_count) emit working_light();
        ++timer_count;
    }

    emit work_ending();
    _is_time_read = false;
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 30.11.2009, 18:02
Сообщение #15


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

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

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




Репутация:   94  


Цитата(AD @ 30.11.2009, 20:27) *
А я правильно понимаю, что это таймер заканчивает свое действие, как только программа выходит из функции run()?
объект таймера будет разрушен по выходу, следовательно от таймера ничего не останется. Только вот метод run() никогда не закончится, а зациклится в методе exec(), также как и функция main()
int main (.....)
{
    QAplication a(...);
...
    a.exec();
}
методы exec() в потоке и в приложении делают примерно одно и тоже
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 30.11.2009, 18:05
Сообщение #16


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

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

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




Репутация:   44  


Цитата(AD @ 30.11.2009, 17:57) *
Не попадает....

В консоль что нибудь пишет?

добавь отладочный вывод:
void ContinueRotation::run()
{
    QTimer timerReading;
    qDebug() << connect(&timerReading,  SIGNAL(timeout()), this, SLOT(reading()));
    
    qDebug() << "Start timer"
    timerReading.start(1000);

    qDebug() << "Start eventloop"
    exec();
    qDebug() << "Stop eventloop"
}

Проверь, запускается ли нитка и т.д.


Цитата(AD @ 30.11.2009, 18:01) *
Так.... попало. Интересно, а такой код приемлем?

Нет.
Твой цикла будет запущен после выхода из метода exec и таймер уже сигналы отправлять не будет.

Ты должен выбрать, или использовать таймер с сигналами и запускать exec, или запускать свой цикл и не использовать таймер.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 30.11.2009, 18:07
Сообщение #17


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

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

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




Репутация:   17  


Ну... я уже ведь сказал, что запускается.... Проблема уже немного в другом: подружить мой цикл и вызов этого таймера... А вот как это сделать?
qDebug() выдает ошибку:
Цитата
error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'QDebug' (or there is no acceptable conversion)

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 30.11.2009, 18:09
Сообщение #18


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

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

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




Репутация:   44  


Цитата(AD @ 30.11.2009, 18:07) *
Ну... я уже ведь сказал, что запускается....

А я уже ответ написал. ;)
Смотри предыдущий ответ.

Цитата(AD @ 30.11.2009, 18:07) *
qDebug() выдает ошибку:
Цитата
error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'QDebug' (or there is no acceptable conversion)


#include <QDebug>

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


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

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

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




Репутация:   17  


Мда... Грустно, что нельзя это сделать. Задачка в следующем, которую никак не могу решить:
В этом потоке я отправляю на COM-порт команды, которые принимает прожектор. Ну команды расшифровываются так: повернуть на столько-то вверх, на столько-то вправо, на столько-то вниз, на столько-то влево. Одновременно мне нужно принимать от прожектора команды и анализировать. Ну что оно уже повернул на столько-то.

В своем цикле у меня делается следующее:
for(int timer_count=0; QTime::currentTime()<=finished_time;)
    {
        if(_finished) break;
        timerTicks();
        if(timer_count == 60) timer_count = 0;
        if(!timer_count) emit working_light();
        ++timer_count;
    }

Имеется счетчик времени. При определенном значении этого счетчика (раз в минуту) запускается функция выдачи команд, которая и занимается отправкой команд:
writing functions
/// Слот работы прожектора - вращения в обеих плоскостях
void ContinueRotation::workSpotlight()
{
    timerTicks();
    geted_angle_elev = -1, geted_azimuth = -1;

    /// Перемещение вниз и вправо до упора
    _angle_elevation = -110 * 10, _azimuth = 170 * 10;
    inf_to_ed_packet.low_angle_elev = LOWBYTE(_angle_elevation);
    inf_to_ed_packet.high_angle_elev = HIGHBYTE(_angle_elevation);
    inf_to_ed_packet.low_azim = LOWBYTE(_azimuth);
    inf_to_ed_packet.high_azim = HIGHBYTE(_azimuth);
    if(imitTsl) imitTsl -> writeFromCtrlContinuous();
    _is_time_read = true;
/// ВОТ ЗДЕСЬ МНЕ И НЕОБХОДИМО ПРОВЕРИТЬ НА СКОЛЬКО ОН УСПЕЛ ПОВЕРНУТЬСЯ.
    timerTicks();

    /// Перемещение вверх и влево до упора
    _angle_elevation = 10 * 10;        _azimuth = -170 * 10;
    inf_to_ed_packet.low_angle_elev = LOWBYTE(_angle_elevation);
    inf_to_ed_packet.high_angle_elev = HIGHBYTE(_angle_elevation);
    inf_to_ed_packet.low_azim = LOWBYTE(_azimuth);
    inf_to_ed_packet.high_azim = HIGHBYTE(_azimuth);
    if(imitTsl) imitTsl -> writeFromCtrlContinuous();
    _is_time_read = true;
/// ВОТ ЗДЕСЬ МНЕ И НЕОБХОДИМО ПРОВЕРИТЬ НА СКОЛЬКО ОН УСПЕЛ ПОВЕРНУТЬСЯ.
    timerTicks();

    /// Возврат в исходное положение
    _angle_elevation = 0;        _azimuth = 0;
    inf_to_ed_packet.low_angle_elev = LOWBYTE(_angle_elevation);
    inf_to_ed_packet.high_angle_elev = HIGHBYTE(_angle_elevation);
    inf_to_ed_packet.low_azim = LOWBYTE(_azimuth);
    inf_to_ed_packet.high_azim = HIGHBYTE(_azimuth);
    if(imitTsl) imitTsl -> writeFromCtrlContinuous();
    timerTicks();
}

Как видно из комментариев есть пара мест, где необходимо проверить значения, что я и пытался реализовать с помощью таймера.

Функции чтения выглядят так:
reading functions
/// Получение азимута
void ContinueRotation::readAzimuth(int& geted_azimuth, double limit)
{
    if(!imitTsl) return;
    QTime begining_time(QTime::currentTime());
    while(geted_azimuth < ((limit - 1.5) * 10) || geted_azimuth > ((limit + 1.5) * 10))
    {
        imitTsl -> readFromCtrlPage();
        geted_azimuth = VALFROMBYTES(inf_from_ed_packet.high_azim, inf_from_ed_packet.low_azim);
        int secs = begining_time.secsTo(QTime::currentTime());
        if(secs > 45) break;
        msleep(10);
    }
}

/// Получение угла места
void ContinueRotation::readAngleElevation(int& geted_angle_elev, double limit)
{
    if(!imitTsl) return;
    QTime begining_time(QTime::currentTime());
    while(geted_angle_elev < ((limit - 1.5) * 10) || geted_angle_elev > ((limit + 1.5) * 10))
    {
        imitTsl -> readFromCtrlPage();
        geted_angle_elev = VALFROMBYTES(inf_from_ed_packet.high_angle_elev, inf_from_ed_packet.low_angle_elev);
        int secs = begining_time.secsTo(QTime::currentTime());
        if(secs > 45) break;
        msleep(10);
    }
}

/// Слот чтения из COM-порта
void ContinueRotation::reading()
{
    if(!_is_time_read) return;

    readAngleElevation(geted_angle_elev, (double)_angle_elevation / 10.);
    readAzimuth(geted_azimuth, (double)_azimuth / 10.);
    _is_time_read = false;
}


Если у кого-то возникнут идеи, как это сделать, буду благодарен. Пока никаких других идей не возникает.... :(

Сообщение отредактировал AD - 30.11.2009, 18:23
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 30.11.2009, 18:19
Сообщение #20


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

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

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




Репутация:   44  


Или делать такой изврат:
void ContinueRotation::run()
{
    connect(imitTsl, SIGNAL(continue_stop()), SLOT(exit()));
    connect(this, SIGNAL(working_light()), SLOT(workSpotlight()));

    QTimer timerReading;
    connect(&timerReading,  SIGNAL(timeout()), this, SLOT(reading()));
    timerReading.start(1000);

   QEventLoop loop;

    for(int timer_count=0; QTime::currentTime()<=finished_time;)
    {
        loop.processEvent();

        if(_finished) break;
        timerTicks();
        if(timer_count == 60) timer_count = 0;
        if(!timer_count) emit working_light();
        ++timer_count;
    }

    emit work_ending();
    _is_time_read = false;
}


Но я бы рекомендовал решить или согналы и exec, или свой цикл без сигналов.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

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


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




RSS Текстовая версия Сейчас: 19.4.2024, 8:47