Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: alexlogvinenkoit от Сентябрь 01, 2011, 18:54



Название: Асинхронность в Qt
Отправлено: alexlogvinenkoit от Сентябрь 01, 2011, 18:54
Доброе время суток!
Делаю прожку на Qt4 в Ubuntu, возникли некоторые сложности...
В общем, есть отдельный поток, который постоянно пытается получить что-нибудь (QByteArray) из сервера...
Сам сервер написан на C++, использует стандартные сокеты, никаких левых библиотек.

Так вот, помимо чтения, в этот сервер нужно еще и передавать данные, по событию (в Qt это, вроде как, slot-ы) нажатия на кнопку... Проблема в том, что соединение с сервером и передача данных осуществляется, но только ПОСЛЕ выхода из приложения (закрытия главного окна)...

Пытаюсь создать новый поток - то же самое... Использую асинхронную функцию (QFuture, QtConcurrent::run()) - все то же!
В чем может быть проблема?
Заранее спасибо!


Название: Re: Асинхронность в Qt
Отправлено: Пантер от Сентябрь 01, 2011, 18:55
Код нужен.


Название: Re: Асинхронность в Qt
Отправлено: LisandreL от Сентябрь 01, 2011, 19:17
Проблема в том, что соединение с сервером и передача данных осуществляется, но только ПОСЛЕ выхода из приложения (закрытия главного окна)...
Это неправильное поведение для Qt.
Практически наверняка у вас ошибка в коде, гадать где именно - практически бесполезно, лучше действительно покажите что да как.


Название: Re: Асинхронность в Qt
Отправлено: alexlogvinenkoit от Сентябрь 01, 2011, 19:34
Показать - плохая идея, т.к. в проекте много файлов... Либо можно сделать миниатюрную версию, для показа...
P.S. Не уверен, что ошибка в коде, т.к. интерфейс рисовался графически (кстати, насколько это есть нехорошо?), а не программно...
И еще, пробовал использовать не Qt-шные потоки (pthread_t) - результат один!
Спасибо!


Название: Re: Асинхронность в Qt
Отправлено: Пантер от Сентябрь 01, 2011, 19:39
Давай сюда минимальный компилябельный пример с данной проблемой.


Название: Re: Асинхронность в Qt
Отправлено: alexlogvinenkoit от Сентябрь 01, 2011, 20:00
//main.cpp

Код:
#include <QtGui/QApplication>
#include "wgtmain.h"
#include "thread.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    wgtMain w;
    w.show();

    Thread th;
    th.start();

    return a.exec();
}

//thread.h

Код:
#ifndef THREAD_H
#define THREAD_H

#include <QThread>
#include <QtNetwork/QTcpSocket>

class Thread : public QThread
{
    Q_OBJECT

    QTcpSocket * sock;
public:
    explicit Thread(QObject *parent = 0);
protected:
    void run();
};

#endif // THREAD_H


//thread.cpp

Код:
#include "thread.h"

Thread::Thread(QObject *parent) :
    QThread(parent)
{
    this->sock = new QTcpSocket(this);
    this->sock->connectToHost("127.0.0.1", 1234);
}

void Thread::run()
{
    while(true)
    {
        QByteArray array = this->sock->readAll();

        if(array.length() > 0)
        {
            if(array.data() == "somedata")
                this->sock->write("somedata_to_send");
        }
    }
}


//wgtmain.h

Код:
#ifndef WGTMAIN_H
#define WGTMAIN_H

#include <QWidget>
#include <QTcpSocket>

namespace Ui {
    class wgtMain;
}

class wgtMain : public QWidget
{
    Q_OBJECT

public:
    explicit wgtMain(QWidget *parent = 0);
    ~wgtMain();

private slots:
    void on_pushButton_clicked();

private:
    Ui::wgtMain *ui;
};

#endif // WGTMAIN_H


//wgtmain.cpp

Код:
#include "wgtmain.h"
#include "ui_wgtmain.h"

wgtMain::wgtMain(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::wgtMain)
{
    ui->setupUi(this);
}

wgtMain::~wgtMain()
{
    delete ui;
}

void wgtMain::on_pushButton_clicked()
{
    QTcpSocket sock (this);
    sock.connectToHost("127.0.0.1", 1234);
    sock.write("some_data_to_sent_from_slot");
    sock.disconnectFromHost();
}



Название: Re: Асинхронность в Qt
Отправлено: Пантер от Сентябрь 01, 2011, 20:03
В on_pushButton_clicked не успевает отправится. Почитай про методы  сокета waitFor*


Название: Re: Асинхронность в Qt
Отправлено: alexlogvinenkoit от Сентябрь 01, 2011, 20:09
В смысле waitForConnected?
Еще вопрос, может немного не по теме (по крайней мере не по этой):
Есть глобальная статическая булевая переменная (bool), так вот, из основного потока (тоже на обработке клика по кнопке) я меняю ее значение, а вот другом потоке, где я ее проверяю - она остается неизменной (проверял отладчиком, сам удивился (смотрю один поток - переменная изменила значение, в другое - нет))... Может подскажете?
Спасибо!


Название: Re: Асинхронность в Qt
Отправлено: alexlogvinenkoit от Сентябрь 01, 2011, 20:12
Проверил waitForConnection(), работает, только, опять же, после завершения работы приложения :)


Название: Re: Асинхронность в Qt
Отправлено: kuzulis от Сентябрь 01, 2011, 20:35
ТС, ты накодил какую то фигню, ИМХО.. Бррр..

И сокет который
Код
C++ (Qt)
this->sock = new QTcpSocket(this);
 
все-равно создается в главном потоке.
Тебе нужно создавать его в run() + создай свой класс MySosket отнаследованный от QTcpSocket
с одним слотом, например slotTransaction();
Код
C++ (Qt)
class MySocket : public QTcpSocket
{
   Q_OBJECT
public:
   MySocket(QObject *parent = 0) : QTcpSocket(parent) {
       connect(this, SIGNAL(readyRead()), this, SLOT(slotTransaction()));
   }
private slots:
   void slotTransaction() {
       QByteArray array = readAll();
       if(array.length() > 0)
       {
           if(array.data() == "somedata")
               write("somedata_to_send");
       }
   }
}
 
...
...
 
void Thread::run()
{
   MySocket sock;
   sock.connectToHost("127.0.0.1", 1234);
   exec();
   sock.disconnectFromHost();
}
 
Как то так.


Название: Re: Асинхронность в Qt
Отправлено: alexlogvinenkoit от Сентябрь 01, 2011, 20:39
ТС, ты накодил какую то фигню, ИМХО.. Бррр..

И сокет который
Код:
this->sock = new QTcpSocket(this);
все-равно создается в главном потоке.
Тебе нужно создавать его в run().

Попробую, спасибо!
P.S. На Qt это мой первый проект, так что не судите строго... Я больше по C++ и VisualC++ (WinAPI) )))))))))))))))


Название: Re: Асинхронность в Qt
Отправлено: kuzulis от Сентябрь 01, 2011, 20:45
См. выше, я дополнил кое что.


Название: Re: Асинхронность в Qt
Отправлено: alexlogvinenkoit от Сентябрь 01, 2011, 20:57
Спасибо!
Вопрос на засыпку: exec() - выполнится 1 раз или будет выполнять бесконечно? while(true) где-то надо вставить?


Название: Re: Асинхронность в Qt
Отправлено: kuzulis от Сентябрь 01, 2011, 21:00
Спасибо!
Вопрос на засыпку: exec() - выполнится 1 раз или будет выполнять бесконечно? while(true) где-то надо вставить?
1. exec() выполнится "бесконечно" (т.е. будет висеть на exec(), т.е. дальше не пойдет. ), т.е exec() запускает обработку Event Loop
2. выйти из exec(), чтобы выполнить дисконнест можно вызвавЖ thread->exit(), при этом, естественно, поток завершится тоже.
3. никаких while не нужно

PS: читай ассистент  ;)


Название: Re: Асинхронность в Qt
Отправлено: popper от Сентябрь 01, 2011, 21:07
Еще вопрос, может немного не по теме (по крайней мере не по этой):
Есть глобальная статическая булевая переменная (bool), так вот, из основного потока (тоже на обработке клика по кнопке) я меняю ее значение, а вот другом потоке, где я ее проверяю - она остается неизменной (проверял отладчиком, сам удивился (смотрю один поток - переменная изменила значение, в другое - нет))... Может подскажете?
Спасибо!
попробуй к переменной добавить модификатор
Код
C++ (Qt)
volatile


Название: Re: Асинхронность в Qt
Отправлено: alexlogvinenkoit от Сентябрь 01, 2011, 21:09
Спасибо еще раз!
А событие на кнопку объяснишь? Было бы супер, очень не хватает :)))