Чтение сетевых данных без readyread() |
Здравствуйте, гость ( Вход | Регистрация )
Чтение сетевых данных без readyread() |
KuvshinoF |
22.4.2021, 10:10
Сообщение
#1
|
Студент Группа: Участник Сообщений: 74 Регистрация: 25.7.2013 Пользователь №: 3887 Спасибо сказали: 0 раз(а) Репутация: 0 |
Задача следующая - постоянно корректно читать сетевые данные (предполагается при запуске потока запускать таймер вычитывания (если они есть конечно) раз в секунду данных из сети). Пример выше не работает - говорит "timer cannot be started from another thread". DataTimer обязателен для некой обработки ситуации отсутствия сетевых данных. И как лучше читать данные - как в примере выше или вместо if сделать while с int size=socket.pendingdatagramsize();? Или лучше как-то по-другому считывать данные? (пробовал вместо таймера запуска чтения данных использовать while(1) {чтение данных} прямо в run, но тогда возникает та же ошибка с таймером DataTimer, который обязателен) |
|
|
Алексей1153 |
22.4.2021, 10:32
Сообщение
#2
|
фрилансер Группа: Участник Сообщений: 2941 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: 34 |
KuvshinoF, объект MyClass создаётся в другом потоке, нежели где будет работать run. Следовательно, поле класса - тоже будет жить там же, где объект.
в данном случае проблему можно решить так: поле класса QTimer DataTimer; - убрать. В run объявить локальную переменную QTimer DataTimer; Также обратить внимание на: QUDPSocket socket; - возможно, нужно синхронизировать доступ к этому полю класса QByteArray array; - возможно, нужно синхронизировать доступ к этому полю класса short addr, port; - возможно, нужно синхронизировать доступ к этим полям класса. Также их нужно инициализировать а я бы так вообще сделал бесконечный цикл внутри void MyClass::run() без вызова exec() , а в цикле подпинывал бы eventDispatcher() Сообщение отредактировал Алексей1153 - 22.4.2021, 10:30 |
|
|
KuvshinoF |
22.4.2021, 15:02
Сообщение
#3
|
Студент Группа: Участник Сообщений: 74 Регистрация: 25.7.2013 Пользователь №: 3887 Спасибо сказали: 0 раз(а) Репутация: 0 |
1. Как же я тогда локальную переменную QTimer DataTimer буду использовать в другом слоте чтения данных myslot? Как мне узнавать момент отсутствия данных (думал сделать таймером с таймаутом через 3 сек.)
2. Что значит (как сделать) синхронизировать доступ? 3. Можно примерчик на подпинывание eventDispatcher() ? |
|
|
Алексей1153 |
22.4.2021, 15:16
Сообщение
#4
|
фрилансер Группа: Участник Сообщений: 2941 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: 34 |
1 - ну, ок, можно оставить полем, однако создать объект таймера нужно в run:
2 - я про межпоточную синхронизацию (возможно, она тут и не требуется, я же не знаю, как это всё у тебя в коде используется) 3 -
Сообщение отредактировал Алексей1153 - 22.4.2021, 15:17 |
|
|
KuvshinoF |
23.4.2021, 15:42
Сообщение
#5
|
Студент Группа: Участник Сообщений: 74 Регистрация: 25.7.2013 Пользователь №: 3887 Спасибо сказали: 0 раз(а) Репутация: 0 |
2. А обязательно создавать умный указатель? ( у меня std не видит метод make_unique)
Если объявить обычный указателеь в хедере, а сделать ему new в run - все равно будет "timers cannot be started from another thread" |
|
|
Алексей1153 |
23.4.2021, 16:03
Сообщение
#6
|
фрилансер Группа: Участник Сообщений: 2941 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: 34 |
KuvshinoF, заголовок #include<memory> включен? Стандарт C++11 или больше включен в настройках?
умный указатель удобнее в плане того, что утечки не будет по невнимательности Если объявить обычный указателеь в хедере, а сделать ему new в run - все равно будет "timers cannot be started from another thread" нет, с обычным указателем тоже должно сработать |
|
|
KuvshinoF |
23.4.2021, 16:58
Сообщение
#7
|
Студент Группа: Участник Сообщений: 74 Регистрация: 25.7.2013 Пользователь №: 3887 Спасибо сказали: 0 раз(а) Репутация: 0 |
#include<memory> включен, иначе бы я не смог бы объявить std::unique_ptr<QTimer>, только make_unique std не видит...В pro-файле прописан с++11 в QMAKE_LFLAGS.
Ну вот с обычным указателем не работает - видимо вообще нельзя запускать таймер в run...или можно? |
|
|
Алексей1153 |
23.4.2021, 17:42
Сообщение
#8
|
фрилансер Группа: Участник Сообщений: 2941 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: 34 |
KuvshinoF, make_unique в C++14 добавлен. А вообще - смело включай 17, а то он уже слегка устаревать начиниет ))
если не разрешают новые стандарты, тогда так
Я сам таймеры в других потоках не создавал (как бы без надобности, у меня в бесконечном цикле используется класс, который отсчитывает пройденный интервал времени пассивно, то есть это выясняется проверкой) но в доке написано так Цитата In multithreaded applications, you can use QTimer in any thread that has an event loop. To start an event loop from a non-GUI thread, use QThread::exec(). Qt uses the timer's thread affinity to determine which thread will emit the timeout() signal. Because of this, you must start and stop the timer in its thread; it is not possible to start a timer from another thread.
|
|
|
KuvshinoF |
26.4.2021, 17:55
Сообщение
#9
|
Студент Группа: Участник Сообщений: 74 Регистрация: 25.7.2013 Пользователь №: 3887 Спасибо сказали: 0 раз(а) Репутация: 0 |
1. Пытаюсь сделать чтение данных без таймера - в run в бесконечном while делаю udpsocket.readDatagram() - выдается ошибка
"socket notifiers cannot be enabled or disabled from another thread" - как это поправить 2. Как при таком методе считывания (п.1) можно ловить (если не таймером) момент отсутствия данных? |
|
|
Алексей1153 |
26.4.2021, 18:09
Сообщение
#10
|
фрилансер Группа: Участник Сообщений: 2941 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: 34 |
udpsocket.readDatagram() - выдается ошибка "socket notifiers cannot be enabled or disabled from another thread" - как это поправить такая же песня, что была с QTimer DataTimer; ак при таком методе считывания (п.1) можно ловить (если не таймером) момент отсутствия данных? элементарно: если udpsocket.hasPendingDatagrams() вернёт false, значит данных нет )) и если processEvents (пост №4) вернул false, значит не было никакой движухи. Тогда можно небольшой слип вызвать ------------------ если не получается, то прикрепи демонстрационный проект, чтобы было с чем покопаться. |
|
|
Текстовая версия | Сейчас: 24.11.2024, 8:51 |