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

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

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: QTcpSocket внутри Qthread  (Прочитано 19157 раз)
BRE
Гость
« Ответ #15 : Июнь 10, 2010, 15:35 »

ну естесственно его надо было переопределить, как же без этого-то! Какой смысл в потоке, если сам run() будет пустым))
Объекты можно создать и извне и перетащить в пространство потока. Так что иногда можно и не переопределять.
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #16 : Июнь 10, 2010, 15:44 »

Можно конечно, но только сейчас заметил, что ТС намекал именно на этот способ, разобрались.
Записан

kubuntu/Win7/x64/NetBeans
Buran
Гость
« Ответ #17 : Июнь 10, 2010, 15:59 »

Тогда вопрос по moveToThread().

Код:
class MyThread : public QThread

MyThread()
{
QTcpSocket socket = new QTcpSocket();
}

void run()
{
socket->write(QByteArray);
}

Когда я обращаюсь из run к socket получаю ошибку невозможности вызова write потому что потоки разные.

а) Праль-но ли я понимаю, что new QTcpSocket() создается в главном потоке. А то, что выполняется в run - это уже мною созданный поток, который совсем-совсем другой?

б) Пробовал использовать socket->moveToThread(this) в конструкторе - не помогает (потоки по прежнему разные), может прямо в run'е прописать этот мув?
Записан
BRE
Гость
« Ответ #18 : Июнь 10, 2010, 16:10 »

а) Праль-но ли я понимаю, что new QTcpSocket() создается в главном потоке. А то, что выполняется в run - это уже мною созданный поток, который совсем-совсем другой?
Правильно.

б) Пробовал использовать socket->moveToThread(this) в конструкторе - не помогает (потоки по прежнему разные)?
Странно. А в консоле при выполнении Qt что пишет?
И код более подробно приведи.
Записан
Buran
Гость
« Ответ #19 : Июнь 10, 2010, 16:58 »


И код более подробно приведи.

Код:
class MyThread : public QThread
{
MyThread()
{
socket = new QTcpSocket();

qDebug() << "OLD socket thread: " << this->thread();  // *1
socket->setParent(0);
socket->moveToThread(this);
qDebug() << "NEW socket thread: " << this->thread();  // *2
}

void run()
{
socket->write(QByteArray);
}

void socketWrite(QByteArray)
{
qDebug() << "WRITE socket thread: " << this->thread();  // *3
socket->write(QByteArray);
}
}

Вывод по точкам:
*1: QThread(0x8d2cd60)
*2: MyThread(0x8e82bc8)
*3: QThread(0x8d2cd60)
Записан
BRE
Гость
« Ответ #20 : Июнь 10, 2010, 17:04 »

socket->setParent(0) можно не писать, ты и так не указал parent объекту socket, т.е. его parent == 0.

Кто вызывает метод socketWrite?

 Строит глазки Два вывода qDebug в конструкторе точно это выводят? Или там все таки socket->thread(), а не this->thread().

И это... объект потока MyThread находится в контексте того потока, в котором он создавался (в главном потоке), поэтому this->thread() должен возвращать всегда одинаковый результат. Если хочешь перенести объект потока в контекст этого потока - ему тоже нужно сказать moveToThread( this ).
Для определения в каком контексте выполняется код, лучше использовать статический метод:
Qt::HANDLE QThread::currentThreadId ()   [static]
« Последнее редактирование: Июнь 10, 2010, 17:19 от BRE » Записан
Buran
Гость
« Ответ #21 : Июнь 10, 2010, 19:31 »

socket->setParent(0) можно не писать, ты и так не указал parent объекту socket, т.е. его parent == 0.

Кто вызывает метод socketWrite?

вызывает его читалка когда в RS приходят данные.



 Строит глазки Два вывода qDebug в конструкторе точно это выводят? Или там все таки socket->thread(), а не this->thread().

Ооооо... Ну конечно опечатался, когда постил. Там конечно же socket->thread()  Улыбающийся
Записан
BRE
Гость
« Ответ #22 : Июнь 10, 2010, 19:37 »

вызывает его читалка когда в RS приходят данные.
А где код, который это реализует. Это слот? Как и где к нему конектятся?
Записан
Buran
Гость
« Ответ #23 : Июнь 10, 2010, 20:17 »

вызывает его читалка когда в RS приходят данные.
А где код, который это реализует. Это слот? Как и где к нему конектятся?


Нет, я уже описывал, что в используемой RS библиотеке readyRead не работает, поэтому сигналы-слоты использовать неудобно. Я в run'е проверяю пришедшие данные в RS  и если пришли - вызов this->socketWrite(пришедший из RS текст).

Т.е. судя по всему я пытаюсь вызвать метод объекта основного потока(MyThread) из дочернего(который выполняется в run).

Так?

« Последнее редактирование: Июнь 10, 2010, 20:23 от Buran » Записан
BRE
Гость
« Ответ #24 : Июнь 10, 2010, 20:28 »

Т.е. судя по всему я пытаюсь вызвать метод объекта основного потока(MyThread) из дочернего(который выполняется в run).
Так?
Все что вызывается из run - выполняется в контексте самого потока.
Вопросы возникают при использовании сигнально-слотовой системы.
Записан
Buran
Гость
« Ответ #25 : Июнь 11, 2010, 00:55 »

Т.е. судя по всему я пытаюсь вызвать метод объекта основного потока(MyThread) из дочернего(который выполняется в run).
Так?
Все что вызывается из run - выполняется в контексте самого потока.
Вопросы возникают при использовании сигнально-слотовой системы.

У меня почему-то не так.

Смотри что получается.

Если делаю moveToThread, то socket->thread() выдает указатель на мой новый, только что созданный поток.
И когда я из run (вот важно!) вызываю socket->socketWrite() и вывожу там указатель (см. код выше), то получаю указатель на основной поток (несмотря на то, что вызвал я его из run). И тут есс-но слоты у меня не арбайтен (потоки-то разные).

А если НЕ делаю, то указатель на поток socket->thread() и тот указатель, что выводится внутри socketWrite() одинаковые и тут связка сигнал-слот работает на отлично. Плохо только, что вызов из run (указатель на поток уже новый) не работает.

Тут родилась идея. Может код работы с RS положить в метод и просто вызывать его из run.
Код:
	void run()
{
this->checkRS()
}

void checkRS()
{
.....
.....
socket->socketWrite()
}

void socketWrite()
{
socket->write()
}

Но ведь в этом случае теряется смысл отдельных потоков, поскольку обработка вызываемых методов будет происходить в основном потоке?
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #26 : Июнь 11, 2010, 02:56 »

И когда я из run (вот важно!) вызываю socket->socketWrite() и вывожу там указатель (см. код выше), то получаю указатель на основной поток (несмотря на то, что вызвал я его из run). И тут есс-но слоты у меня не арбайтен (потоки-то разные).

В код особо не вникал, но
Код
C++ (Qt)
socket = new QTcpSocket();
 
ты создал в главном.
Я вобщем-то всегда считал (где-то на этом же форуме даже встретил тему с похожей ситуацией когда-то), что если ты вызываешь методы какого-либо объекта, не важно в каком потоке, то они, методы эти, будут выполнятся в контексте того потока, в котором был создан объект.
А что касается соединения главного с второстепенным посредством сигнала/слота, то лучше воспользоваться типом (соединения) DirectConnection - тогда этот слот выполнится в контексте второстепенного, имею ввиду если сигнал будет испускать второстепенный, - вдруг пригодится...
« Последнее редактирование: Июнь 11, 2010, 03:01 от serg_hd » Записан

kubuntu/Win7/x64/NetBeans
BRE
Гость
« Ответ #27 : Июнь 11, 2010, 07:08 »

У меня почему-то не так.

Смотри что получается.

Если делаю moveToThread, то socket->thread() выдает указатель на мой новый, только что созданный поток.
И когда я из run (вот важно!) вызываю socket->socketWrite() и вывожу там указатель (см. код выше), то получаю указатель на основной поток (несмотря на то, что вызвал я его из run). И тут есс-но слоты у меня не арбайтен (потоки-то разные).
Это потому что ты не так проверяешь. Чуть выше я писал:
Цитировать
Для определения в каком контексте выполняется код, лучше использовать статический метод:
Qt::HANDLE QThread::currentThreadId ()   [static]
Метод QObject::thread() возвращает указатель на поток, которому этот объект принадлежит. Используется это значение в методе connect для определения какой тип подключения выбрать для соединения объектов.

Так же я писал, что сам объект класса MyThread принадлежит создающему его поток (главному например). Поэтому, если ты в этом классе описал слоты и хочешь что-бы они выполнялись в контексте нового потока MyThread, то этот объект нужно переместить в контекст этого потока.
Код
C++ (Qt)
MyThread::MyThread()
{
moveToThread( this ); // Перемещаем сам объект класса MyThread в контекст его потока
...
}
 
Записан
Buran
Гость
« Ответ #28 : Июнь 11, 2010, 15:25 »

Для определения в каком контексте выполняется код, лучше использовать статический метод:
Qt::HANDLE QThread::currentThreadId ()   [static]

Пасиб, пропустил. Действительно выводит совсем другие значения.)


Код
C++ (Qt)
MyThread::MyThread()
{
moveToThread( this );
...
}
 


А когда он переместится в ново-созданный поток, есть ощущение, что мне снова надо будет запускать очередь сообщений exec'ом.
И в run'е я не смогу выполнять проверку RS.

Так?
Записан
BRE
Гость
« Ответ #29 : Июнь 11, 2010, 15:39 »

А когда он переместится в ново-созданный поток, есть ощущение, что мне снова надо будет запускать очередь сообщений exec'ом.
Ну на самом деле никуда ничего не переноситься. Все потоки одного процесса выполняются в одном адресном пространстве. Эта конструкция просто отмечает к какому потоку будет относиться объект, для выполнения корректного коннекта (я чуть выше про это писал).
Если нужно получать сигналы в потоке, то без exec не обойтись. Его придется запускать.

И в run'е я не смогу выполнять проверку RS.
Так?
Попробуй по таймеру проверять состояние RS в этом же потоке. Запусти таймер и в обработчике сигнала timeout проверяй его состояние.
Записан
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


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