Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: не могу разобраться с QThread
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие
MishaUA
На qt пересел почти год назад, все это время старался не использовать потоки, но сейчас необходимо их использовать для работы с QSerialPort. Изначально код разрабатываемой программы был написан без QThread, но после добавления некоторого функционала я начал переделывать обмен данными QSerialPort через QThread. Проблема в том, что даже без использования сигналов и слотов прием данных по СОМ порту не работал, но передача работала отлично. Думаю, для приема QSerialPort использует сигналы и/или слоты, которые у меня в потоках не работают. Чтобы не писать слишком много кода, я сделал простейший пример, который у меня не запустился:
class Thr : public QObject
{
    Q_OBJECT
public:
    Thr() {
        QThread*   comThread = new QThread();

        this->moveToThread(comThread);

        connect(comThread, SIGNAL(started()), this, SLOT(run()));
        connect(this, SIGNAL(finished()), comThread, SLOT(terminate()));

        comThread->start();
    }

public slots:
    void run() {
        // таймер
        QTimer* tim = new QTimer();
        connect(tim, SIGNAL(timeout()), this, SLOT(timerTimeout()));
        tim->start(2000);

        qDebug() << "run";  // это вызывается

        while(thread()->isRunning()) thread()->sleep(1);   // торчим здесь

        emit finished();
    }

    void timerTimeout() {
        qDebug() << "timerTimeout"; // это не вызывается
    }

signals:
    void finished();
};


Код простейший. Создаю в главном файле через Thr* comThread = new Thr();.
Как видно с комментариев, не вызывается обработчик сигнала таймера. Возможно, слот с компонент, вызывающий сигнал находятся в разных потоках, из-за чего не работают.

PS: возможно натупил, спать хочу)))
Trisch
А эти строки обязательны:
        while(thread()->isRunning()) thread()->sleep(1);   // торчим здесь

        emit finished();


а то без них все работает.
MishaUA
работает потому что в вашем случае поток завершается после выхода с функции run. Мне нужно чтобы работали сигналы и слоты, а так же, цикл потока, который в while(thread()->isRunning()) {какой то код}
Trisch
Цитата(MishaUA @ 6.10.2013, 11:35) *
работает потому что в вашем случае поток завершается после выхода с функции run. Мне нужно чтобы работали сигналы и слоты, а так же, цикл потока, который в while(thread()->isRunning()) {какой то код}


ну так сигналы и слоты работают. Просто до них не доходит очередь, так как данный циклы while(thread()->isRunning()) {какой то код} вечен.
Litkevich Yuriy
Цитата(MishaUA @ 6.10.2013, 5:20) *
class Thr : public QObject
Напрашивается мысль о том, что наследоваться надо было от QThread и делать всё, как в примерах работы с потоками
MishaUA
судя по этой статье http://habrahabr.ru/post/150274/ , примеры не правильны
Trisch
Цитата(MishaUA @ 6.10.2013, 15:14) *
судя по этой статье http://habrahabr.ru/post/150274/ , примеры не правильны


Судя по данной статье. Для нового потока, желательно, выделить отдельный класс.
Так же, при инициализации данного класса, желательно, ему сменить родителя с помощью void QObject::moveToThread ( QThread * targetThread ).

Кстати, вот есть еще статейка по этому поводу http://devdoc.web-ide.ru/index.php/content/view/qt_threads.htm
kuzulis
Цитата
Проблема в том, что даже без использования сигналов и слотов прием данных по СОМ порту не работал, но передача работала отлично.


Неужели? В самом деле? Все сгорели карусели? (с)

Не верю. Показаывай код.
MishaUA
сделал так:
class Thr : public QThread
{
    Q_OBJECT
public:
    Thr() {
        QTimer* tim = new QTimer(this);
        connect(tim, SIGNAL(timeout()), this, SLOT(timerTimeout()));
        tim->start(2000);

        this->start();
    }

public slots:
    virtual void run() {
        qDebug() << "run";  // это вызывается

        while(isRunning()) {// торчим здесь
            sleep(1);
        }

        terminate();
    }

    void timerTimeout() {
        qDebug() << "timerTimeout";
    }

signals:
    void finished();
};

Согласно статье по моей ссылке, это не правильно, но тем не менее, работает исправно.
Только меня волнует вопрос: почему срабатывают слоты, если нет exec() ?
Litkevich Yuriy
Цитата(MishaUA @ 7.10.2013, 21:17) *
почему срабатывают слоты, если нет exec() ?
а это никак не зависит от exec()
Нет exec() нет отдельного потока, сигнально-слотовые связи устанавлияваются непосредственно, а не через очередь событий.
Yuriy
Цитата(MishaUA @ 7.10.2013, 20:17) *
Только меня волнует вопрос: почему срабатывают слоты, если нет exec() ?

Потому, что объекты имитирующие и принимающие сигнал принадлежат одному потоку, а именно - основному. В Вашем примере отдельный поток порождается в методе run(). Таймер размещается в конструкторе и никак вновь порожденному потоку не принадлежит. Перенесите размещение таймера в метод run() и "работать" все перестанет.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.