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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Потоки, слоты и сигналы  (Прочитано 4710 раз)
silart
Гость
« : Май 26, 2008, 07:14 »

Добрый день. Нужно сделать так, чтоб в GUI приложении существовал дополнительный поток, который периодически бы опрашивал устройство, и полученные данные данные передавались бы в главный поток, который обрабатывает GUI.
Вот как я пробовал решить проблему:

Код:
class DeviceScanner : public QThread
{
Q_OBJECT

private:
const QVector<boost::shared_ptr<eNod3> >& Devices;
int Interval;

private slots:
void slotTimeOut();
signals:
void Weighted(QString);

private:
void run();

public:
DeviceScanner(QObject *parent, const QVector<boost::shared_ptr<eNod3> >& devices, int interval);
~DeviceScanner();
};

DeviceScanner::DeviceScanner(QObject *parent, const QVector<boost::shared_ptr<eNod3> >& devices, int interval)
: QThread(parent), Devices(devices), Interval(interval)
{
start();
}

DeviceScanner::~DeviceScanner()
{
quit();
}

void DeviceScanner::slotTimeOut()
{
QString s;

// Че-то там...
emit Weighted( s );
}

void DeviceScanner::run()
{
QTimer t;
connect(&t, SIGNAL(timeout()), SLOT(slotTimeOut()));
t.start(Interval);

exec();
}


Проблема в том, что слот slotTimeOut() выполняет совсем не наш поток, а поток GUI. Как сделать так, чтобы сигналы таймера обрабатывались в нашем стороннем потоке?
Записан
Alex03
Гость
« Ответ #1 : Май 26, 2008, 11:38 »

Ибо получатель сигнала - потомок QThread, создан в GUI-потоке...
Способ коннекта по дефолту Qt::AutoConnection.
Цитировать
Qt::AutoConnection If the signal is emitted from the thread in which the receiving object lives, the slot is invoked directly, as with Qt::DirectConnection; otherwise the signal is queued, as with Qt::QueuedConnection.
Попробуйте так:
Код:
connect(&t, SIGNAL(timeout()), SLOT(slotTimeOut()), Qt::DirectConnection);
Записан
Alex03
Гость
« Ответ #2 : Май 26, 2008, 11:51 »

Но сразу предупрежу что сигнал Weighted(QString) по умолчанию коннектится по всей видимости между объектами главного (GUI) потока, и соответственно используется Qt::DirectConnection. Поэтому могут возникнуть некоторые грабельки уже сдесь.
Т.е. для того коннеккта нужен ConnectionType - Qt::QueuedConnection.
Возможно лучше написать свой класс, который порождать в run() и уже к нему (или прямо в нём) коннектить QTimer.

Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #3 : Май 26, 2008, 12:57 »

2 silart: Сделайте цикл со sleep в методе run вместо таймера и выолняйте все необходимые действия здесь (в run)
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Alex03
Гость
« Ответ #4 : Май 26, 2008, 13:43 »

А то и вообще не использовать QTimer/sleep(), а пользовать чтонибудь типа select() или WaitForXXXXX() в зависимости от того что за устройство (драйвер) и какая ОС (и там и там можно задавать таймауты).
Записан
Sergeich
Гость
« Ответ #5 : Май 26, 2008, 18:05 »

Как-то так:
Код:
class DeviceScanner : public QObject
{
Q_OBJECT
public:
DeviceScanner( QObject *parent, const QVector<boost::shared_ptr<eNod3> >& devices ) : QObject(parent), devs(devices) {}
public slots:
void scan();
signals:
void weighted( const QString& );
private:
const QVector<boost::shared_ptr<eNod3> >& devs;
};


class DeviceThread : public QThread
{
Q_OBJECT
public:
DeviceThread(QObject *parent, const QVector<boost::shared_ptr<eNod3> >& devices, int interval);
~DeviceScanner();
signals:
void Weighted( const QString& );
private:
const QVector<boost::shared_ptr<eNod3> >& Devices;
int Interval;
void run();
};


DeviceThread::DeviceThread(QObject *parent, const QVector<boost::shared_ptr<eNod3> >& devices, int interval)
: QThread(parent), Devices(devices), Interval(interval)
{
start();
}

DeviceThread::~DeviceThread()
{
quit();
}


void DeviceThread::run()
{
QTimer timer;
DeviceScanner scanner(0, Devices);

connect(&timer, SIGNAL(timeout()), &scanner, SLOT(scan()));
connect(&scanner, SIGNAL(weighted()), this, SIGNAL(Weighted()));
timer.start(Interval);
exec();
}
« Последнее редактирование: Май 26, 2008, 18:28 от Sergeich » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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