Russian Qt Forum

Qt => Работа с сетью => Тема начата: zayac_val от Январь 30, 2009, 19:32



Название: Работа с потоками
Отправлено: zayac_val от Январь 30, 2009, 19:32
Помогите разобраться с потоками.
Хочу написать клиент-серверное приложение, и по задумке каждый вновь создаваемый сокет должен работать в отдельном потоке. Работа потока начинается с выполнения функции run(), в котрой я и создаю свой сокет:
Код:
class Socket : public QTcpSocket
{
  Q_OBJECT
public:
   ClientServer *window;
   Socket(int sockDeskr,QObject *parent);
public slots:
   void read();
   void read_error();
   void deleteLater();
   void write();

};

class Thread : public QThread
{
  Q_OBJECT
public:
  ClientServer *window;
  Thread(int sockDeskr,QObject *parent);
  void run();
private:
   int sockDeskr;
};

Socket::Socket(int sockDeskr,QObject *parent):QTcpSocket(parent)
{
    window=(ClientServer *)parent;
     this->setSocketDeskriptor(sockDeskr);
  connect(this,SIGNAL(readyRead()),this,SLOT(read()));
  connect(this,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(read_error()));
  connect(window->pushButton_3,SIGNAL(clicked()),this,SLOT(write()));
}

void Socket::read()
{
  QByteArray bar=this->readAll();
          QString str;
          str.append(bar);
          window->textEdit->setText(str); 
}

void Socket::read_error()
{
  QMessageBox *mb=new QMessageBox(this);
          mb->setText(codec->toUnicode("Ошибка сокета: ")+this->errorString());
          mb->exec();
}

void Socket::write()
{
  QByteArray bar;
  bar.append(window->textEdit->toPlainText());
  this->write(bar);
}

/////////////////////////////////////////////////////////<-----------Thread-------->/////////////////////////
void Thread::Thread(int sockDeskr,QObject *parent)
{
  this->sockDeskr=sockDeskr;
  window=(ClientServer *)parent;
}

void Thread::run()
{
Socket *soc=new Socket(sockDeskr,window);
}
Сокет при такой реализации будет работать в отдельном потоке, или я в потоке просто создаю экземпляр сокета и не более, и для правильной работы мне надо реализовывать слоты для сокета в классе Thread.


Название: Re: Работа с потоками
Отправлено: Dendy от Январь 30, 2009, 20:48
Вижу вы даже не пробовали запускать своё приложение. Во-первых, зачем вы наследуетесь от QTcpSocket? Во вторых создавать и использовать экземпляры QWidget можно только в главном потоке. Поток должен знать только о своей задаче, и ни про что более вроде GUI классов.


Название: Re: Работа с потоками
Отправлено: zayac_val от Февраль 02, 2009, 15:28
Вижу вы даже не пробовали запускать своё приложение. Во-первых, зачем вы наследуетесь от QTcpSocket? Во вторых создавать и использовать экземпляры QWidget можно только в главном потоке. Поток должен знать только о своей задаче, и ни про что более вроде GUI классов.

Приложение действительно не запускал, т.к.  хотелось сначала правильно организовать структуру программы. От  QTcpSocket наследуюсь, т.к. хотелось чтоб работа сокета и все нужные для этого слоты были реализованы в отдельном классе. Раз использовать экземпляры QWidget в дочернем потоке нельзя, то на сколько я понимаю отдавать результаты работы надо, через какой-то буфер. Но меня больше интересует методы объекта создаваемого в функции run() класса Thread будут выполнятся в дочернем потоке, или в основном ?


Название: Re: Работа с потоками
Отправлено: Dendy от Февраль 02, 2009, 15:35
Цитировать
От  QTcpSocket наследуюсь, т.к. хотелось чтоб работа сокета и все нужные для этого слоты были реализованы в отдельном классе.

Для этого наследоваться не нужно.

Цитировать
Но меня больше интересует методы объекта создаваемого в функции run() класса Thread будут выполнятся в дочернем потоке, или в основном ?

События обьекта будут выполняться в том потоке, которому принадлежит обьект. А принадлежит он тому потоку, в котором был создан.


Название: Re: Работа с потоками
Отправлено: kuzulis от Февраль 02, 2009, 15:41
2 zayac_val , посмотри примерчик http://www.prog.org.ru/topic_8455_30.html

там в самом конце пример... если яправильно понял

попробуй этот же пример, предварительно заккоментировав по очереди строчки:
Код:
    tB->cB->moveToThread(tB);
    tA->cA->moveToThread(tA);

и посмотри в чем разница

ЗЫ: может пригодится :)
ЗЫЗЫ: тока в этом примере память утекает куда-то :)


Название: Re: Работа с потоками
Отправлено: zayac_val от Февраль 03, 2009, 20:33
У меня клиент-серверное приложение, сокет(клиента) я создал в основном потоке, при коннекте к серверу в нем создается дочерний поток в котором создается сокет, предназначенный для общения с сокетом из основного потока. Проблема как обмениваться сигналами между потоками. Т.е. когда один сокет вызывает функцию write(), другой сокет сигнал readyRead не получает.


Название: Re: Работа с потоками
Отправлено: ритт от Февраль 03, 2009, 21:02
т.е.
Код:
void Thread::Thread(int sockDeskr,QObject *parent)
{
  this->sockDeskr=sockDeskr;
  window=(ClientServer *)parent;
}

void Thread::run()
{
Socket *soc=new Socket(sockDeskr,window);
}
//...
QTcpSocket* socket = new QTcpSocket(this);
socket->connectToHost(...);
Thread* thread = new Thread(socket->socketDescriptor(), this);
и вопрос - почему soc->read() (в потоке thread) не срабатывает на socket->write(...) (в потоке main)?
я правильно всё понял?


Название: Re: Работа с потоками
Отправлено: pastor от Февраль 03, 2009, 22:03
BWT:

Код
C++ (Qt)
Socket *soc=new Socket(sockDeskr,window);

Socket создается во вспомогательном потоке, parent (window) создается в главном потоке. Это случайно не противоречит:

Цитировать
The child of a QObject must always be created in the thread where the parent was created.


Название: Re: Работа с потоками
Отправлено: zayac_val от Февраль 04, 2009, 09:49
т.е.
Код:
void Thread::Thread(int sockDeskr,QObject *parent)
{
  this->sockDeskr=sockDeskr;
  window=(ClientServer *)parent;
}

void Thread::run()
{
Socket *soc=new Socket(sockDeskr,window);
}
//...
QTcpSocket* socket = new QTcpSocket(this);
socket->connectToHost(...);
Thread* thread = new Thread(socket->socketDescriptor(), this);
и вопрос - почему soc->read() (в потоке thread) не срабатывает на socket->write(...) (в потоке main)?
я правильно всё понял?


Да, именно так. И еще вопрос из той же облсти, как сигналы от формы, например нажатие кнопки, передавать в вспомогательный поток ?


Название: Re: Работа с потоками
Отправлено: kuzulis от Февраль 04, 2009, 10:22
Цитировать
У меня клиент-серверное приложение, сокет(клиента) я создал в основном потоке, при коннекте к серверу в нем создается дочерний поток в котором создается сокет, предназначенный для общения с сокетом из основного потока.

я шот не понял..
1. а зачем спри коннекте к серверу создавать в потоке еще один сокет?
2. какой смысл обмена сигналами между сокетами одного приложения ?

2 zayac_val , и посмотри все-таки ту ссылку шо я привел.. т.к там именно то что тебе нужно (ИМХО).. и не важно что там не сокеты! :)
т.к. там рассматривался "общий" пример по сути принципа создания потоков и выполнению методов в ЭТИХ потоках, а не в главном потоке!


Название: Re: Работа с потоками
Отправлено: ритт от Февраль 04, 2009, 16:26
Да, именно так.
readyRead() клиентского сокета эмитится, когда сокет на сервере пишет данные, но уж никак не тогда, когда сам клиентский сокет пишет данные. поэтому такой бред работать не будет.

И еще вопрос из той же облсти, как сигналы от формы, например нажатие кнопки, передавать в вспомогательный поток ?
читай QObject::connect - это базовый материал, без знания которого вообще не стОит лезть в кутэ.


Название: Re: Работа с потоками
Отправлено: pastor от Февраль 05, 2009, 13:59
2 zayac_val: а чего бы вам не поизучать  QTDIR/examples/network/fortuneclient и QTDIR/examples/network/threadedfortuneserver?


Название: Re: Работа с потоками
Отправлено: zayac_val от Февраль 09, 2009, 16:37
Вся беда была из-за того, что не был запущен цикл обработки сообщений, т.е. метод exec(); в функции run(); потока. 
       Dendy говорил, что :" создавать и использовать экземпляры QWidget можно только в главном потоке", но, на сколько я понииаю, использовать в второстепенном потоке указатель на форму  для соединения сигналов от формы с слотами потока, и наоборот, для соединения сигналов от потока с слотами формы никто не запрещает, или я опять неправ ? ???


Название: Re: Работа с потоками
Отправлено: Dendy от Февраль 12, 2009, 10:04
Соединения сигналов со слотами можно делать из любых потоков. Как и любые другие классы - потомки QWidget могут иметь потокобезопастные методы, которые должны оговариваться отдельно в документации к конкретному классу.