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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Циклический(бесконечный) опрос QTcpSocket в потоке QThread  (Прочитано 6143 раз)
calipsofirst
Гость
« : Февраль 27, 2012, 08:49 »

Есть гуи приложение, из которого создается класс Sock, который в свою очередь наследует QThread. Соответственно, класс Sock имеет виртуальный метод run, в котором создается экземпляр QTcpSocket и соединяются сигналы данного экземпляра со слотами класса Sock (connected, disconnected, readyRead) и потом происходит запрос соединения(connectToHost). Затем должен начаться циклический опрос данных с удаленного устройства. Но есть проблема: если зацыклить здесь опрос, но не запускается метод exec(), указаный в конце тела run(). Ну и понятно, что без exec() не работает event loop и не работает не одно событие... даже как таковая отправка данных по QTcpSocket->write(). Но если дать запуститься методу exec(), то я не понимаю где тогда запускать циклический опрос данных. Пробовал запускать циклический опрос из слота connected(), предполагая, что через этот слот опрос будет выполняться "параллельно" методу exec(), но в этом случает "виснет" главное окно, как будто опрос происходит в основном потоке (хотя по соединению сигнал-слот должен вызываться из потока). Метод moveToThread никакого эффекта не дает. В общем, прощу помощи найти рабочее решение для организации циклического опроса в потоке. Перечитал много веток на этом форуме и на других, но не смог найти в них что то полезное, к тому же большинство топиков посвящено созданию сервера в потоке. Для тестирования создал небольшой проект, его здесь и приведу:

MainWindow.cpp

Код:
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    sock = new Sock(this);
    connect(sock, SIGNAL(getData(QByteArray)), this, SLOT(onGetData(QByteArray)));
    sock->start(QThread::NormalPriority);   
}

void MainWindow::onGetData(QByteArray data)
{
    ui->lineEdit->setText(data.toHex());
}

sock.h
Код:
#include <QThread>
#include <QTcpSocket>

class Sock : public QThread
{
    Q_OBJECT
public:
    explicit Sock(QObject *parent = 0);
    void run();

signals:
    void getData(QByteArray data);

public slots:
    void onReadyRead();
    void onConnect();
    void onDisconnect();

private:
    QTcpSocket *gsock;

    void requestLoop();
};


sock.cpp
Код:
#include "QtNetwork"

#include "sock.h"

Sock::Sock(QObject *parent) :
    QThread(parent)
{   

}

void Sock::onReadyRead()
{
    qDebug("ready read");
    qint64 bytes = gsock->bytesAvailable();
    QByteArray data = gsock->read(bytes);

    emit getData(data);
}

void Sock::onConnect()
{
    qDebug("connect");
//    requestLoop();

}

void Sock::onDisconnect()
{
    qDebug("disconnect");
}

void Sock::run()
{   
    qDebug("run");   

    gsock = new QTcpSocket(0);

    connect(gsock, SIGNAL(readyRead()), this, SLOT(onReadyRead()), Qt::QueuedConnection);
    connect(gsock, SIGNAL(connected()), this, SLOT(onConnect()), Qt::QueuedConnection);
    connect(gsock, SIGNAL(disconnected()), this, SLOT(onDisconnect()), Qt::QueuedConnection);

    QHostAddress host;
    host.setAddress("192.168.0.17");
    gsock->connectToHost(host, 502);
    if(!gsock->waitForConnected())
    {
        qDebug("connected faild");
        return;
    }
    else
        qDebug("connected success");

    requestLoop();

    qDebug("exec");
    exec();
    qDebug("stop exec");
}

void Sock::requestLoop()
{
    QByteArray data;
    data.append(QByteArray::fromHex("000100000006010350160002"));
    while(1)
    {
        if (gsock->state() == QAbstractSocket::ConnectedState)
        {
            qDebug("write data");
            gsock->write(data);         
        }
        else
        {
            qDebug("no connected to write");
        }
        sleep(2);
    }
}
Записан
calipsofirst
Гость
« Ответ #1 : Февраль 27, 2012, 08:53 »

Забыл указать версии: Qt 4.8.0, mingw32 4.4.0, winxp xp3, qt creator 2.4.1. Все действие происходит в виртуалке vmware player. Но на хосте debian testing все тоже самое.
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #2 : Февраль 27, 2012, 10:37 »

Sock хоть и является потоком сам живёт в основном потоке, соответственно его слоты будут выполняться в основной гуй потоке.
Записан
calipsofirst
Гость
« Ответ #3 : Февраль 27, 2012, 19:46 »

Хм.. странно, ведь сокет создается в потоке...  Но как бы то ни было, проблему я решил, поставив в цикле (requestLoop) QEventLoop с методом processEvents() таким образом:

Код:
void Sock::requestLoop()
{
    QByteArray data;
    data.append(QByteArray::fromHex("000100000006010350160002"));
    QEventLoop loop;
    while(1)
    {
        if (gsock->state() == QAbstractSocket::ConnectedState)
        {
            qDebug("write data");
            gsock->write(data);         
        }
        else
        {
            qDebug("no connected to write");
        }
        loop.processEvents();
        sleep(2);
    }
}
Записан
Alatey
Гость
« Ответ #4 : Май 31, 2012, 18:04 »

Здесь про exec() http://www.devdoc.ru/index.php/content/view/qt_threads.htm
По-моему exec() запускается что-бы поток обрабатывал свои слоты. А если читать данные в бесконечном цикле то ставишь этот цикл в run(), а exec() - ненужен.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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