По каким-то причинам не работает таймер, который я хочу запустить в параллельном потоке.
В чем могут быть проблемы?
/// Класс потока - вращение вокруг осей заданное количество времени - длительное вращение
class ContinueRotation: public QThread
{
Q_OBJECT
private:
QTimer _timerReading; ///< таймер для запуска чтения из COM-порта
public:
void startTimerReading() { _timerReading.start(1000); }
};
/// Запуск потока вращения в обеих плоскостях длительный промежуток времени
void ContinueRotation::run()
{
connect(&_timerReading, SIGNAL(timeout()), this, SLOT(reading()));
///
}
/// Запуск работы прожектора - ГЛАВНЫЙ поток
void ContinuousWork::startControl()
{
///
_continue -> startTimerReading();
_continue -> start();
}
1. Обрати внимание, таймер создается в главном потоке!
2. В run() добавь exec().
/// Запуск потока вращения в обеих плоскостях длительный промежуток времени
void ContinueRotation::run()
{
connect(&_timerReading, SIGNAL(timeout()), this, SLOT(reading()));
_timerReading.start(1000);
///................
exec();
}
AD, таймер так и остался в главном потоке.
Помести его в run().
П.С. А собственно будет ли влиять положение таймера, ведь ему не устанавливается родительский объект?
/// Класс потока - вращение вокруг осей заданное количество времени - длительное вращение
class ContinueRotation: public QThread
{
Q_OBJECT
private:
QTimer _timerReading; ///< таймер для запуска чтения из COM-порта
private slots:
void reading();
};
/// Запуск потока вращения в обеих плоскостях длительный промежуток времени
void ContinueRotation::run()
{
/// ................
connect(&_timerReading, SIGNAL(timeout()), this, SLOT(reading()));
_timerReading.start(1000);
/// for(int timer_count=0; QTime::currentTime()<=finished_time;) { .... }
/// ..........
exec();
}
BRE, понял, ведь это следует из задачи
Мда... Руки у меня, что-ли, кривые.... Не выходит....
/// Запуск потока вращения в обеих плоскостях длительный промежуток времени
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);
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;
timerReading.stop();
exec();
}
Проверка и испускание сигнала от таймера происходит в цикле обработки событий, который запускается методом exec.
А у тебя к этому времени таймер уже остановлен.
Блин. Я убрал строку остановки таймера, но в слот все-равно программа не заходит... Что еще может быть не так?
Попробуй такой код:
void ContinueRotation::run()
{
QTimer timerReading;
connect(&timerReading, SIGNAL(timeout()), this, SLOT(reading()));
timerReading.start(1000);
exec();
}
Не попадает....
Так.... попало. Интересно, а такой код приемлем?
/// Запуск потока вращения в обеих плоскостях длительный промежуток времени
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;
}
int main (.....)
{
QAplication a(...);
...
a.exec();
}
методы exec() в потоке и в приложении делают примерно одно и тоже
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"
}
Ну... я уже ведь сказал, что запускается.... Проблема уже немного в другом: подружить мой цикл и вызов этого таймера... А вот как это сделать?
qDebug() выдает ошибку:
Мда... Грустно, что нельзя это сделать. Задачка в следующем, которую никак не могу решить:
В этом потоке я отправляю на 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;
}
/// Слот работы прожектора - вращения в обеих плоскостях
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();
}
/// Получение азимута
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;
}
Или делать такой изврат:
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;
}
AD, ты уже в который раз спускаешся до подробностей прикладного кода, складывается такое впечатление, что ты хочешь чтобы за тебя программу написали.
Что делает этот код?
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;
}
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)