Название: QTcpSocket внутри Qthread Отправлено: Buran от Июнь 10, 2010, 13:01 Приветствую всех.
Есть вопрос по QThread. Создаю примерно так: Код: MyThread : public QThread И действительно, this - показывает указывает на один thread, а socket->thread() - на другой. Т.е. new QtcpSocket() создается в отдельном потоке. Наверное так и должно быть? Вопрос: Как мне создать socket в моем потоке? Чтобы this и socket->thread() возвращали указатель на один и тот же thread? Или может мне socket'у указать socket->MoveToThread(this) (это только идея). UPD: Прочитал, что можно вызвать в функции run(). Но теперь не приходит SIGNAL(readyRead()). Почему? Ведь очередь сообщений теперь в моем новом потоке, а не в основном. Подскажите, пжл, чего я не догоняю? Название: Re: QTcpSocket внутри Qthread Отправлено: serg_hd от Июнь 10, 2010, 13:20 UPD: потому что поток умирает вместе с объектами которые были в нём созданы. Поставь в run()'e exec(), и глуши его когда надо будетПрочитал, что можно вызвать в функции run(). Но теперь не приходит SIGNAL(readyRead()). Почему? Ведь очередь сообщений теперь в моем новом потоке, а не в основном. Подскажите, пжл, чего я не догоняю? Название: Re: QTcpSocket внутри Qthread Отправлено: Buran от Июнь 10, 2010, 14:04 UPD: потому что поток умирает вместе с объектами которые были в нём созданы. Поставь в run()'e exec(), и глуши его когда надо будетПрочитал, что можно вызвать в функции run(). Но теперь не приходит SIGNAL(readyRead()). Почему? Ведь очередь сообщений теперь в моем новом потоке, а не в основном. Подскажите, пжл, чего я не догоняю? Брррр.... У меня поток не умирает. Он работает, это легко подтверждается выполняемым в нем кодом. И emit слота же работает! Не срабатывает сигнал: Код: class MyThread : public QThread Насколько я понимаю, это может быть только если: а) умер socket. Но, socket есть, можно запросить на него указатель.; б) что-то с очередью сообщений; UPD: Кажись exec() как раз очередь сообщений и запускает. Сейчас проверю....) Название: Re: QTcpSocket внутри Qthread Отправлено: BRE от Июнь 10, 2010, 14:31 потому что поток умирает вместе с объектами которые были в нём созданы. Поставь в run()'e exec(), и глуши его когда надо будет По умолчанию в QThread::run как раз один exec() и запускается.Название: Re: QTcpSocket внутри Qthread Отправлено: BRE от Июнь 10, 2010, 14:32 Код
Название: Re: QTcpSocket внутри Qthread Отправлено: Buran от Июнь 10, 2010, 14:52 Код
Ура! Очередь сообщений заработала. Но вот выполнение потока остановилось.( Если быть точным, то кроме связывания сигнала и слота в run() еще есть while(). Внутри которого идет постоянное выполнение кода. И вот при exec() оно (выполнение кода в while()) останавливается. Пока не очень понимаю почему. Название: Re: QTcpSocket внутри Qthread Отправлено: BRE от Июнь 10, 2010, 14:56 Пока не очень понимаю почему. Потому, что в exec() запускается бесконечный цикл обработки событий.Ты должен определиться, что тебе нужно. Если нужна возможность получения сигналов, то нужен exec (точнее обработка событий) и тогда с выполнением другого кода в потоке нужно думать. Расскажи, что ты хочешь обрабатывать в цикле while()? Название: Re: QTcpSocket внутри Qthread Отправлено: serg_hd от Июнь 10, 2010, 15:02 Совершенно не понял фразы
По умолчанию в QThread::run как раз один exec() и запускается. А это Код
Название: Re: QTcpSocket внутри Qthread Отправлено: Buran от Июнь 10, 2010, 15:04 Расскажи, что ты хочешь обрабатывать в цикле while()? По событию socket, SIGNAL(readyRead()) происходит обработка сокета. А в while постоянно мониторится RS-232. Т.к. в QextSerialPort нифига не работает сигнал readyRead() я его (RS) просматриваю вручную. Данные в потоке кидаются между ними. В принципе, в никсах, я могу это обойти привязавшись к файлу /dev/ttyS# и смотреть его notify(). Но тогда в винда (в случае чего) мне не светит. Название: Re: QTcpSocket внутри Qthread Отправлено: BRE от Июнь 10, 2010, 15:09 По событию socket, SIGNAL(readyRead()) происходит обработка сокета. Ты в одном потоке и RS-232 мониторишь и из сетки данные получаешь?А в while постоянно мониторится RS-232. Т.к. в QextSerialPort нифига не работает сигнал readyRead() я его (RS) просматриваю вручную. Название: Re: QTcpSocket внутри Qthread Отправлено: Buran от Июнь 10, 2010, 15:10 По событию socket, SIGNAL(readyRead()) происходит обработка сокета. Ты в одном потоке и RS-232 мониторишь и из сетки данные получаешь?А в while постоянно мониторится RS-232. Т.к. в QextSerialPort нифига не работает сигнал readyRead() я его (RS) просматриваю вручную. Угу. Название: Re: QTcpSocket внутри Qthread Отправлено: serg_hd от Июнь 10, 2010, 15:11 BRE, ну так что ты хотел сказать насчёт exec()?
Название: Re: QTcpSocket внутри Qthread Отправлено: BRE от Июнь 10, 2010, 15:15 BRE, ну так что ты хотел сказать насчёт exec()? То, что если run() не переопределять, то там как раз exec() и запускается. А вот если переопределять, то его нужно вызывать явно или вызывать QThread::run():Код
Название: Re: QTcpSocket внутри Qthread Отправлено: BRE от Июнь 10, 2010, 15:20 Угу. Можно запустить таймер в этом потоке и через заданный интервал проверять состояние порта или разнести получение данных из сети и проверку порта по разным потокам.Название: Re: QTcpSocket внутри Qthread Отправлено: serg_hd от Июнь 10, 2010, 15:25 [То, что если run() не переопределять, то там как раз exec() и запускается. А вот если переопределять, то его нужно вызывать явно или вызывать QThread::run(): ну естесственно его надо было переопределить, как же без этого-то! Какой смысл в потоке, если сам run() будет пустым))Код
Название: Re: QTcpSocket внутри Qthread Отправлено: BRE от Июнь 10, 2010, 15:35 ну естесственно его надо было переопределить, как же без этого-то! Какой смысл в потоке, если сам run() будет пустым)) Объекты можно создать и извне и перетащить в пространство потока. Так что иногда можно и не переопределять.Название: Re: QTcpSocket внутри Qthread Отправлено: serg_hd от Июнь 10, 2010, 15:44 Можно конечно, но только сейчас заметил, что ТС намекал именно на этот способ, разобрались.
Название: Re: QTcpSocket внутри Qthread Отправлено: Buran от Июнь 10, 2010, 15:59 Тогда вопрос по moveToThread().
Код: class MyThread : public QThread Когда я обращаюсь из run к socket получаю ошибку невозможности вызова write потому что потоки разные. а) Праль-но ли я понимаю, что new QTcpSocket() создается в главном потоке. А то, что выполняется в run - это уже мною созданный поток, который совсем-совсем другой? б) Пробовал использовать socket->moveToThread(this) в конструкторе - не помогает (потоки по прежнему разные), может прямо в run'е прописать этот мув? Название: Re: QTcpSocket внутри Qthread Отправлено: BRE от Июнь 10, 2010, 16:10 а) Праль-но ли я понимаю, что new QTcpSocket() создается в главном потоке. А то, что выполняется в run - это уже мною созданный поток, который совсем-совсем другой? Правильно.б) Пробовал использовать socket->moveToThread(this) в конструкторе - не помогает (потоки по прежнему разные)? Странно. А в консоле при выполнении Qt что пишет?И код более подробно приведи. Название: Re: QTcpSocket внутри Qthread Отправлено: Buran от Июнь 10, 2010, 16:58 И код более подробно приведи. Код: class MyThread : public QThread Вывод по точкам: *1: QThread(0x8d2cd60) *2: MyThread(0x8e82bc8) *3: QThread(0x8d2cd60) Название: Re: QTcpSocket внутри Qthread Отправлено: BRE от Июнь 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] Название: Re: QTcpSocket внутри Qthread Отправлено: Buran от Июнь 10, 2010, 19:31 socket->setParent(0) можно не писать, ты и так не указал parent объекту socket, т.е. его parent == 0. Кто вызывает метод socketWrite? вызывает его читалка когда в RS приходят данные. ::) Два вывода qDebug в конструкторе точно это выводят? Или там все таки socket->thread(), а не this->thread(). Ооооо... Ну конечно опечатался, когда постил. Там конечно же socket->thread() :) Название: Re: QTcpSocket внутри Qthread Отправлено: BRE от Июнь 10, 2010, 19:37 вызывает его читалка когда в RS приходят данные. А где код, который это реализует. Это слот? Как и где к нему конектятся?Название: Re: QTcpSocket внутри Qthread Отправлено: Buran от Июнь 10, 2010, 20:17 вызывает его читалка когда в RS приходят данные. А где код, который это реализует. Это слот? Как и где к нему конектятся?Нет, я уже описывал, что в используемой RS библиотеке readyRead не работает, поэтому сигналы-слоты использовать неудобно. Я в run'е проверяю пришедшие данные в RS и если пришли - вызов this->socketWrite(пришедший из RS текст). Т.е. судя по всему я пытаюсь вызвать метод объекта основного потока(MyThread) из дочернего(который выполняется в run). Так? Название: Re: QTcpSocket внутри Qthread Отправлено: BRE от Июнь 10, 2010, 20:28 Т.е. судя по всему я пытаюсь вызвать метод объекта основного потока(MyThread) из дочернего(который выполняется в run). Все что вызывается из run - выполняется в контексте самого потока.Так? Вопросы возникают при использовании сигнально-слотовой системы. Название: Re: QTcpSocket внутри Qthread Отправлено: Buran от Июнь 11, 2010, 00:55 Т.е. судя по всему я пытаюсь вызвать метод объекта основного потока(MyThread) из дочернего(который выполняется в run). Все что вызывается из run - выполняется в контексте самого потока.Так? Вопросы возникают при использовании сигнально-слотовой системы. У меня почему-то не так. Смотри что получается. Если делаю moveToThread, то socket->thread() выдает указатель на мой новый, только что созданный поток. И когда я из run (вот важно!) вызываю socket->socketWrite() и вывожу там указатель (см. код выше), то получаю указатель на основной поток (несмотря на то, что вызвал я его из run). И тут есс-но слоты у меня не арбайтен (потоки-то разные). А если НЕ делаю, то указатель на поток socket->thread() и тот указатель, что выводится внутри socketWrite() одинаковые и тут связка сигнал-слот работает на отлично. Плохо только, что вызов из run (указатель на поток уже новый) не работает. Тут родилась идея. Может код работы с RS положить в метод и просто вызывать его из run. Код: void run() Но ведь в этом случае теряется смысл отдельных потоков, поскольку обработка вызываемых методов будет происходить в основном потоке? Название: Re: QTcpSocket внутри Qthread Отправлено: serg_hd от Июнь 11, 2010, 02:56 И когда я из run (вот важно!) вызываю socket->socketWrite() и вывожу там указатель (см. код выше), то получаю указатель на основной поток (несмотря на то, что вызвал я его из run). И тут есс-но слоты у меня не арбайтен (потоки-то разные). В код особо не вникал, но Код ты создал в главном. Я вобщем-то всегда считал (где-то на этом же форуме даже встретил тему с похожей ситуацией когда-то), что если ты вызываешь методы какого-либо объекта, не важно в каком потоке, то они, методы эти, будут выполнятся в контексте того потока, в котором был создан объект. А что касается соединения главного с второстепенным посредством сигнала/слота, то лучше воспользоваться типом (соединения) DirectConnection - тогда этот слот выполнится в контексте второстепенного, имею ввиду если сигнал будет испускать второстепенный, - вдруг пригодится... Название: Re: QTcpSocket внутри Qthread Отправлено: BRE от Июнь 11, 2010, 07:08 У меня почему-то не так. Это потому что ты не так проверяешь. Чуть выше я писал:Смотри что получается. Если делаю moveToThread, то socket->thread() выдает указатель на мой новый, только что созданный поток. И когда я из run (вот важно!) вызываю socket->socketWrite() и вывожу там указатель (см. код выше), то получаю указатель на основной поток (несмотря на то, что вызвал я его из run). И тут есс-но слоты у меня не арбайтен (потоки-то разные). Цитировать Для определения в каком контексте выполняется код, лучше использовать статический метод: Метод QObject::thread() возвращает указатель на поток, которому этот объект принадлежит. Используется это значение в методе connect для определения какой тип подключения выбрать для соединения объектов.Qt::HANDLE QThread::currentThreadId () [static] Так же я писал, что сам объект класса MyThread принадлежит создающему его поток (главному например). Поэтому, если ты в этом классе описал слоты и хочешь что-бы они выполнялись в контексте нового потока MyThread, то этот объект нужно переместить в контекст этого потока. Код
Название: Re: QTcpSocket внутри Qthread Отправлено: Buran от Июнь 11, 2010, 15:25 Для определения в каком контексте выполняется код, лучше использовать статический метод: Qt::HANDLE QThread::currentThreadId () [static] Пасиб, пропустил. Действительно выводит совсем другие значения.) Код
А когда он переместится в ново-созданный поток, есть ощущение, что мне снова надо будет запускать очередь сообщений exec'ом. И в run'е я не смогу выполнять проверку RS. Так? Название: Re: QTcpSocket внутри Qthread Отправлено: BRE от Июнь 11, 2010, 15:39 А когда он переместится в ново-созданный поток, есть ощущение, что мне снова надо будет запускать очередь сообщений exec'ом. Ну на самом деле никуда ничего не переноситься. Все потоки одного процесса выполняются в одном адресном пространстве. Эта конструкция просто отмечает к какому потоку будет относиться объект, для выполнения корректного коннекта (я чуть выше про это писал).Если нужно получать сигналы в потоке, то без exec не обойтись. Его придется запускать. И в run'е я не смогу выполнять проверку RS. Попробуй по таймеру проверять состояние RS в этом же потоке. Запусти таймер и в обработчике сигнала timeout проверяй его состояние.Так? Название: Re: QTcpSocket внутри Qthread Отправлено: ieroglif от Июнь 11, 2010, 18:21 не понимаю - зачем держать оба обработчика (на сеть и на железку) в одном потоке?
имхо, это не логично. что если разнести их по разным потокам? в потоке на железку будет спокойно себе крутиться цикл проверки железки и когда надо сигналить байтарреем в слот потока работы с сетью.. не катит? Название: Re: QTcpSocket внутри Qthread Отправлено: BRE от Июнь 11, 2010, 18:23 не понимаю - зачем держать оба обработчика (на сеть и на железку) в одном потоке? Ответ, на аналогичное предложение (несколькими постами выше), тоже не получил. ::)имхо, это не логично. что если разнести их по разным потокам? в потоке на железку будет спокойно себе крутиться цикл проверки железки и когда надо сигналить байтарреем в слот потока работы с сетью.. не катит? Название: Re: QTcpSocket внутри Qthread Отправлено: Buran от Июнь 12, 2010, 18:40 Ответ, на аналогичное предложение (несколькими постами выше), тоже не получил. ::) Предложение логичное и даже очень. Правда таких кроссов (сеть-КОМ) может быть и десяток и тогда таких потоков будет как минимум n*2+1 Хм... Вы предлагаете мне сдаться...?! Это не путь настоящих Джедаев. Где ж я еще такие грабли найду...это же чистое знание.)) Название: Re: QTcpSocket внутри Qthread Отправлено: ieroglif от Июнь 12, 2010, 19:54 Ответ, на аналогичное предложение (несколькими постами выше), тоже не получил. ::) Предложение логичное и даже очень. Правда таких кроссов (сеть-КОМ) может быть и десяток и тогда таких потоков будет как минимум n*2+1 Хм... Вы предлагаете мне сдаться...?! Это не путь настоящих Джедаев. Где ж я еще такие грабли найду...это же чистое знание.)) 1. зачем такие извращения? один поток опрашивает 10 железок по очереди (или 2 потока по 5 железок) - я уверен что будет нормально работать, так же как и 1-2 потока на 10 сетевых соединений Название: Re: QTcpSocket внутри Qthread Отправлено: pethead от Ноябрь 05, 2010, 20:34 я сделал так.
создал класс потока с сокетом внутри, и сразу его засунул movetothread самого в себя. прописал в нем сигнал\слоты на события сокета: прием, таймаут. в нем запущен exec. создал еще один поток, и его засунул самого в себя,в run теперь цикл while, в котором я управляю сокетным потоком через сигналы. оба потока принадлежат одному классу (не от QObject, поэтому он сам не может участвовать в сигнал\слотах). |