class MyClass:: public QThread()
{
...
void run();
QTimer DataTimer;
QUDPSocket socket;
QByteArray array;
short addr, port;
public slots:
void myslot();
void noData();
}
////////////////////////////////////////////////////////////
MyClass::MyClass()
{
}
///////////////////////////////////////////////////////////
void MyClass::run()
{
DataTimer.setInterval(3000);
connect(&DataTimer, SIGNAL(timeout()), this, SLOT(noData()));
QTimer timer;
connect(&timer, SIGNAL(timeout()), this, SLOT(myslot()), Qt::DirectConnection);
timer.start(1000);
exec();
}
///////////////////////////////////////////////////////////
void MyClass::myslot()
{
if (socket.hasPendingDatagrams())
{
DataTimer.stop();
int size = socket.bytesAvailable();
array.resize(size);
socket.readDatagram(array.data(), size, &addr, &port);
// обработка данных
DataTimer.start();
}
}
///////////////////////////////////////////////////////////
void MyClass::noData()
{
}
///////////////////////////////////////////////////////////
KuvshinoF, объект MyClass создаётся в другом потоке, нежели где будет работать run. Следовательно, поле класса - тоже будет жить там же, где объект.
в данном случае проблему можно решить так:
поле класса QTimer DataTimer; - убрать.
В run объявить локальную переменную QTimer DataTimer;
Также обратить внимание на:
QUDPSocket socket; - возможно, нужно синхронизировать доступ к этому полю класса
QByteArray array; - возможно, нужно синхронизировать доступ к этому полю класса
short addr, port; - возможно, нужно синхронизировать доступ к этим полям класса. Также их нужно инициализировать
а я бы так вообще сделал бесконечный цикл внутри void MyClass::run() без вызова exec() , а в цикле подпинывал бы eventDispatcher()
1. Как же я тогда локальную переменную QTimer DataTimer буду использовать в другом слоте чтения данных myslot? Как мне узнавать момент отсутствия данных (думал сделать таймером с таймаутом через 3 сек.)
2. Что значит (как сделать) синхронизировать доступ?
3. Можно примерчик на подпинывание eventDispatcher() ?
1 - ну, ок, можно оставить полем, однако создать объект таймера нужно в run:
class MyClass:: public QThread()
{
...
private:
std::unique_ptr<QTimer> DataTimer;
....
};
void MyClass::run()
{
DataTimer=std::make_unique<QTimer>();
connect(&DataTimer.get(), SIGNAL(timeout()), this, SLOT(noData()));
...
...
DataTimer->start(3000);
exec();
}
void MyClass::myslot()
{
if (socket.hasPendingDatagrams())
{
if(DataTimer)DataTimer->stop();
...
...
if(DataTimer)DataTimer->start();
}
}
#include <QAbstractEventDispatcher>
void .....::run()
{
while(!isInterruptionRequested())
{
if(!eventDispatcher()->processEvents(QEventLoop::AllEvents))
{
//никаких сообщений сейчас не было.
//Тут по надобности можно чуть притормозить поток,
//например, вызвать
//msleep(1);
}
}
}
2. А обязательно создавать умный указатель? ( у меня std не видит метод make_unique)
Если объявить обычный указателеь в хедере, а сделать ему new в run - все равно будет "timers cannot be started from another thread"
KuvshinoF, заголовок #include<memory> включен? Стандарт C++11 или больше включен в настройках?
умный указатель удобнее в плане того, что утечки не будет по невнимательности
#include<memory> включен, иначе бы я не смог бы объявить std::unique_ptr<QTimer>, только make_unique std не видит...В pro-файле прописан с++11 в QMAKE_LFLAGS.
Ну вот с обычным указателем не работает - видимо вообще нельзя запускать таймер в run...или можно?
KuvshinoF, make_unique в C++14 добавлен. А вообще - смело включай 17, а то он уже слегка устаревать начиниет ))
если не разрешают новые стандарты, тогда так
DataTimer.reset(new QTimer);
1. Пытаюсь сделать чтение данных без таймера - в run в бесконечном while делаю udpsocket.readDatagram() - выдается ошибка
"socket notifiers cannot be enabled or disabled from another thread" - как это поправить
2. Как при таком методе считывания (п.1) можно ловить (если не таймером) момент отсутствия данных?
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)