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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: QThread и бесконечный цикл в потоке  (Прочитано 12506 раз)
titan83
Гость
« : Октябрь 07, 2013, 15:05 »

Здравствуйте.
Попользовался и гуглом, и местным поиском, но так и не решил свою проблему, поэтому пишу.
Есть поток, в котором вызывается poll() для контроля файлов на sysfs, это поток оформлен в виде бесконечного цикла, и именно его зацикленность порождает сообщение - QThread: Destroyed while thread is still running, но сообщение бы можно было игнорировать, а вот процесс-зомби уже мешает - приложение после этого повторно не запускается - завершается с кодом 0 на функции QThread::start().
Возможно, что я действую идеологически неправильно, тогда было бы здорово получить пинок в нужное направление.
Спасибо.
Привожу основные моменты кода:

class QMyObject: public QObject
{
Q_OBJECT

public slots:
    void getKey(int keyCode)
    {
        if (keyCode == -1)
        {
            emit exit();
        }
    }
signals:
    void exit(void);

};

class PollThread : public QThread
{
Q_OBJECT

private:

public:
    void run()
    {
        while(true)
        {
            poll(fdset, 2, 500);

            if (fdset[1].revents & POLLPRI)
            {
                switch (rx[0])
                {
                } /* switch (rx[0]) */

                emit keyPressed(keyCode);
            } /* if (fdset[0].revents & POLLPRI) */
        } /* while(true) */
    } /* void run() */

signals:
    void keyPressed(int);
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    PollThread keyb_thread;
    QMyObject myObject;

    QObject::connect(&keyb_thread, SIGNAL(keyPressed(int)), &tabWidget, SLOT(setCurrentIndex(int)));
    QObject::connect(&keyb_thread, SIGNAL(keyPressed(int)), &myObject, SLOT(getKey(int)));
    QObject::connect(&keyb_thread, SIGNAL(finished()), &myObject, SLOT(deleteLater()));
    QObject::connect(&myObject, SIGNAL(exit()), &a, SLOT(closeAllWindows()));

    keyb_thread.start();

    return a.exec();
}
Записан
mutineer
Гость
« Ответ #1 : Октябрь 07, 2013, 15:19 »

Завершай поток перед тем, как уничтожать связанный с ним QThread. Например заведи volatile переменную и проверяй ее на каждой итерации цикла.
« Последнее редактирование: Октябрь 07, 2013, 15:24 от mutineer » Записан
titan83
Гость
« Ответ #2 : Октябрь 07, 2013, 15:43 »

Завершай поток перед тем, как уничтожать связанный с ним QThread. Например заведи volatile переменную и проверяй ее на каждой итерации цикла.
Спасибо. Как я понимаю - это обычный return?
Надеялся, что без это удастся обойтись.
Записан
mutineer
Гость
« Ответ #3 : Октябрь 07, 2013, 15:59 »

Да, надо выйти из run()

Ну и перед удалением QThread подождать его при помощи wait()
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #4 : Октябрь 07, 2013, 16:28 »

a select() вместо poll() может спасти отца русской демократии? Улыбающийся
Записан

ArchLinux x86_64 / Win10 64 bit
mutineer
Гость
« Ответ #5 : Октябрь 07, 2013, 16:31 »

А чем оно поможет? Разве select неблокирующий?
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #6 : Октябрь 07, 2013, 16:32 »

А тем, что можно убрать QThread и использовать QSocketNotifier Улыбающийся
Записан

ArchLinux x86_64 / Win10 64 bit
mutineer
Гость
« Ответ #7 : Октябрь 07, 2013, 16:35 »

Извини, но я не вижу связи между заменой poll() на select() и заменой всего этого на QSocketNotifier. Можешь пояснить?
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #8 : Октябрь 07, 2013, 16:39 »

Код
C++ (Qt)
 
QSocketNotifier sysfsNotifier(ourWatchedSysfsDescriptor);
 
connect(sysfsNotifier, SIGNAL(activated(int)), this, SLOT(onActivated(int)));
sysfsNotifier.setEnabled(true);
 
 
MyClass::onActivated(int)
{
   // do something
}
 
 
Записан

ArchLinux x86_64 / Win10 64 bit
mutineer
Гость
« Ответ #9 : Октябрь 07, 2013, 16:40 »

А где тут замена poll на select?
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #10 : Октябрь 07, 2013, 16:41 »

Эмм.. QSocketNotifier использует select() если не ошибаюсь. Поэтому, если ТС-у можно заменить poll() на select(), то можно заменить весь его Thread на QSocketNotifier (или на несколько ) и не парить мосг.

Т.е. следить за дескриптором в *nix (за евентами типа read/write/error) достаточно при помощи QSocketNotifier.
« Последнее редактирование: Октябрь 07, 2013, 16:45 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
titan83
Гость
« Ответ #11 : Октябрь 08, 2013, 10:19 »

Эмм.. QSocketNotifier использует select() если не ошибаюсь. Поэтому, если ТС-у можно заменить poll() на select(), то можно заменить весь его Thread на QSocketNotifier (или на несколько ) и не парить мосг.

Т.е. следить за дескриптором в *nix (за евентами типа read/write/error) достаточно при помощи QSocketNotifier.
Денис, спасибо! То, что надо!
А то FileWatcher базируется на inotify, о она события на sysfs не ловит(
Записан
titan83
Гость
« Ответ #12 : Октябрь 08, 2013, 13:31 »

Хм, а у меня получить адекватную работу QSocketNotifier пока не получилось(
В слоте от нотифера я вычитываю данные из наблюдаемого файла, как я это делал раньше с select(), при этом удается прочесть адекватные данные только один раз, потом read() всегда возвращает число считанных байт ноль. Пробовал вычитывать и ReadAll() и просто read() из stdio - результат одинаковый. А раз я не вычитываю, то у меня сыплются постоянные прерывания от нотифера. Может есть пример заведомо рабочего кода?
Спасибо.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #13 : Октябрь 08, 2013, 14:27 »

Покажи твой код с QSocketNotifier.
Записан

ArchLinux x86_64 / Win10 64 bit
titan83
Гость
« Ответ #14 : Октябрь 08, 2013, 14:48 »

Тут проблема не в нотифире, видимо. Делаю просто

            file = open("/test", O_RDWR | O_NONBLOCK);

            while(true)
            {
                read(file, &c, 1);
                qDebug() << QString::number(c);
                read(file, &c, 1);
                qDebug() << QString::number(c);
            }
Файл содержит два байта - 52 и 10.
В первой итерации цикла все читается правильно, потом оба байта читаются как 10.
Посмотрел свои проекты на чистом си - там все аналогично происходит с select() и все работает.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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