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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Асинхронность в Qt  (Прочитано 10584 раз)
alexlogvinenkoit
Гость
« : Сентябрь 01, 2011, 18:54 »

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

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

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

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #1 : Сентябрь 01, 2011, 18:55 »

Код нужен.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


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


Просмотр профиля
« Ответ #2 : Сентябрь 01, 2011, 19:17 »

Проблема в том, что соединение с сервером и передача данных осуществляется, но только ПОСЛЕ выхода из приложения (закрытия главного окна)...
Это неправильное поведение для Qt.
Практически наверняка у вас ошибка в коде, гадать где именно - практически бесполезно, лучше действительно покажите что да как.
Записан
alexlogvinenkoit
Гость
« Ответ #3 : Сентябрь 01, 2011, 19:34 »

Показать - плохая идея, т.к. в проекте много файлов... Либо можно сделать миниатюрную версию, для показа...
P.S. Не уверен, что ошибка в коде, т.к. интерфейс рисовался графически (кстати, насколько это есть нехорошо?), а не программно...
И еще, пробовал использовать не Qt-шные потоки (pthread_t) - результат один!
Спасибо!
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #4 : Сентябрь 01, 2011, 19:39 »

Давай сюда минимальный компилябельный пример с данной проблемой.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
alexlogvinenkoit
Гость
« Ответ #5 : Сентябрь 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();
}

Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #6 : Сентябрь 01, 2011, 20:03 »

В on_pushButton_clicked не успевает отправится. Почитай про методы  сокета waitFor*
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
alexlogvinenkoit
Гость
« Ответ #7 : Сентябрь 01, 2011, 20:09 »

В смысле waitForConnected?
Еще вопрос, может немного не по теме (по крайней мере не по этой):
Есть глобальная статическая булевая переменная (bool), так вот, из основного потока (тоже на обработке клика по кнопке) я меняю ее значение, а вот другом потоке, где я ее проверяю - она остается неизменной (проверял отладчиком, сам удивился (смотрю один поток - переменная изменила значение, в другое - нет))... Может подскажете?
Спасибо!
Записан
alexlogvinenkoit
Гость
« Ответ #8 : Сентябрь 01, 2011, 20:12 »

Проверил waitForConnection(), работает, только, опять же, после завершения работы приложения Улыбающийся
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #9 : Сентябрь 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();
}
 
Как то так.
« Последнее редактирование: Сентябрь 01, 2011, 20:46 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
alexlogvinenkoit
Гость
« Ответ #10 : Сентябрь 01, 2011, 20:39 »

ТС, ты накодил какую то фигню, ИМХО.. Бррр..

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

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

Сообщений: 2812


Просмотр профиля
« Ответ #11 : Сентябрь 01, 2011, 20:45 »

См. выше, я дополнил кое что.
Записан

ArchLinux x86_64 / Win10 64 bit
alexlogvinenkoit
Гость
« Ответ #12 : Сентябрь 01, 2011, 20:57 »

Спасибо!
Вопрос на засыпку: exec() - выполнится 1 раз или будет выполнять бесконечно? while(true) где-то надо вставить?
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #13 : Сентябрь 01, 2011, 21:00 »

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

PS: читай ассистент  Подмигивающий
« Последнее редактирование: Сентябрь 01, 2011, 21:04 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
popper
Гость
« Ответ #14 : Сентябрь 01, 2011, 21:07 »

Еще вопрос, может немного не по теме (по крайней мере не по этой):
Есть глобальная статическая булевая переменная (bool), так вот, из основного потока (тоже на обработке клика по кнопке) я меняю ее значение, а вот другом потоке, где я ее проверяю - она остается неизменной (проверял отладчиком, сам удивился (смотрю один поток - переменная изменила значение, в другое - нет))... Может подскажете?
Спасибо!
попробуй к переменной добавить модификатор
Код
C++ (Qt)
volatile
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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