Russian Qt Forum
Ноябрь 26, 2024, 08:36 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QThread  (Прочитано 3163 раз)
Firefox
Гость
« : Июнь 26, 2013, 09:35 »

Здравствуйте подскажите по такому вопросу: создаю отдельный класс, пытаюсь его запустить в новом потоке. В методе run() стартую таймер. Но когда по сигналу из основного потока пытаюсь сменить интервал таймера, то выдает ошибку, что не возможно убить и стартовать объект из другого потока. как правильно обратиться к объекту таймера в потоке уже созданном, чтоб это было корректно?и правильно ли поток запускается, а то при старте тоже пишет ошибку?
//Класс потока
Код:
//.h
class CalkRastr: public QThread
{
    Q_OBJECT
public:
    CalkRastr();
    ~CalkRastr();
protected:
    void run();

private:
    QTimer *tPrepict;
    void Prepicture();
   
public slots:
  void NewScale(unsigned char scale); // изменение интервала таймера при изменении шкалы в СОРД

private slots:
   void SlotPrepic();

};
//.cpp
void CalkRastr::run()
{
    tPrepict=new QTimer(this);
    connect(tPrepict,SIGNAL(timeout()),SLOT(SlotPrepic()));
    tPrepict->start(135);
    exec();
}
void CalkRastr::SlotPrepic()
{
    Prepicture();
    emit SendDataToSord(&Mas_ind[0][0]);
}
void CalkRastr::NewScale(unsigned char scale)
{
    if(scale==0)
        tPrepict->setInterval(135);
    if(scale==1)
        tPrepict->setInterval(270);
    if(scale==2)
        tPrepict->setInterval(540);
    if(scale==3)
        this->tPrepict->setInterval(1080);
    if(scale==4)
        tPrepict->setInterval(1340);
    Scale=scale;
}
// основной поток
Код:
//.h
class MainWindow : public QMainWindow
                 
{
    Q_OBJECT
   
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    QTimer *tmSord, *tmBor;
    void newScale(unsigned char Scale);
 
private:
    Ui::MainWindow *ui;
   
    CalkRastr *calcRst;

signals:
   
    void SigNewScale(unsigned char);
private slots:
   

};

//.cpp
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
 calcRst=new CalkRastr();
 connect(this,SIGNAL(SigNewScale(unsigned char)),calcRst,SLOT(NewScale(unsigned char)));
calcRst->start();

}
void MainWindow::newScale(unsigned char Scale)
 {
     if(oldScale!=Scale)
     {
         oldScale=Scale;
         emit SigNewScale(oldScale);
     }
 }


Ввыводе приложения в QtCreator пишет следующие ошибки(фиолетовым):
при старте процесса:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is CalkRastr(0xc5b0048), parent's thread is QThread(0xab27130), current thread is CalkRastr(0xc5b0048)
при смене интервала таймера:
QObject::killTimer: timers cannot be stopped from another thread
QObject::startTimer: timers cannot be started from another thread
Записан
Bepec
Гость
« Ответ #1 : Июнь 26, 2013, 09:43 »

Или используй "moveToThread(this)" в конструкторе потока, или же кидай moveToThread при создании в самого себя.

Создавать и убивать в другом потоке нельзя. Зато можно вызвать слот и тогда он будет радостно исполняться в своём потоке (если конечно тип соединения - очередь).
Записан
Firefox
Гость
« Ответ #2 : Июнь 26, 2013, 09:47 »

если я поставлю moveToThread(this) в конструкторе класса, то разве не создастся новый поток при вызове start()? И немного не понятно, я же вызываю слот из класса потока CalkRastr, почему это другой поток получается?
« Последнее редактирование: Июнь 26, 2013, 09:49 от Firefox » Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #3 : Июнь 26, 2013, 16:47 »

Вы создаете объект потока CalkRastr в основном потоке.
А QTimer вы создаете уже в другом по токе.

Попробуйте так
Выслать сигнал из основного потока и привязать его к слоту объекта потока CalkRastr.
А из слота объекта потока CalkRastr выслать сигнал для смены  интервала таймера(или наоборот, как хотите).
Должно помочь.

Потом

Код
C++ (Qt)
void CalkRastr::run()
{
tPrepict=new QTimer(this); //УБРАТЬ this!!!
...
}
 

иначе Ваш таймер будет дочерним от CalkRastr, а он создан в основном потоке.
« Последнее редактирование: Июнь 26, 2013, 16:53 от demaker » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Июнь 26, 2013, 17:13 »

если я поставлю moveToThread(this) в конструкторе класса, то разве не создастся новый поток при вызове start()?
Создастся и так и так. Осуждаемое moveToThread(this) просто говорит в каком потоке объект должен принимать сигналы/события (какой eventLoop)
Записан
Bepec
Гость
« Ответ #5 : Июнь 26, 2013, 17:27 »

Уточняю свою реплику - при moveToThread(this) все объекты класса,наследованного от QThread будут созданы в его потоке. В ином случае все создаваемые объекты в иных методах, кроме как run будут созданы в потоке родителя вашего унаследованного класса.

Как то так.
Записан
Firefox
Гость
« Ответ #6 : Июнь 27, 2013, 09:33 »

Спасибо большое всем за советы.все заработало и в голове немного прояснилось. Улыбающийся
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.125 секунд. Запросов: 22.