crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

5 страниц V   1 2 3 > »   
Ответить в данную темуНачать новую тему
> Проблемы с многопотоковым приложением, Работа с второстепенным потоком.
AD
  опции профиля:
сообщение 4.2.2008, 19:23
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Есть главное приложение, где выполняется отрисовка карты и траектории. А есть второстепенный поток, который читает файлы(логи) для отрисовки траектории. Как правильно передать управление из одной функции в другую? И вообще как правильнее решить этот вопрос. Вот примеры функций.
class LogReader
class LogReader: public QObject
{
    Q_OBJECT

protected:
        std::vector<Uint> m_vBlock;                ///< вектор прочитанных слов
        FILE* file;                                ///< файл загрузки (лог-файл)
    public:
        std::vector<ParamDescr*> rec_descr;        ///< вектор параметров из файла описания (файла загрузки)
        RThread* rthread;                        ///< указатель объект класса потока
        int count_files;                        ///< количество непрочитанных файлов
    protected:
        LOGRECORD ParseBlock();
                void ChangeDateTime(LOGRECORD& t, std::string compared_time, std::string compared_date);
                
                //.............
                std::vector<LOGRECORD> TRead();
                
};

/// Чтение файла загрузки
    vector<LOGRECORD> LogReader::TRead()
    {
        Uint var = (Uint)1E+6;
        bool bBlock = false;
        bool file_read = false;
        vector<LOGRECORD> log;
        time_t before_read;
        time(&before_read);
        while(fread(&var, sizeof(var), 1, file) > 0 && !feof(file))
        {
            Suint adr = var % 256;
            /// Определение начала/конца одной записи и записывание ее в вектор
            switch(adr)
            {
            case 0000:
                m_vBlock.clear();
                bBlock = true;
                break;
            case 0001:
                if(bBlock)
                {
                    LOGRECORD t = ParseBlock();
                    ChangeDateTime(t, "cur_time", "cur_date");
                    log.push_back(t);
                    file_read = true;
                    /// Сравнение временных меток
                    time_t contin_read;
                    time(&contin_read);
                    time_t delta = contin_read - before_read;
                    if(delta > 5)
                    {
                        rthread -> stop();
                        //rthread -> wait(1000);
                    }
                }
                bBlock = false;
                break;
            default:
                if(bBlock)
                    m_vBlock.push_back(var);
            }
        }

        /// Закрываем файл с логом
        ShutDown();
        /// Уменьшаем список непрочитанных файлов
        if(file_read)
        {
            --count_files;
            rthread -> stop();
        }

        return log;
    }

class RThread: public QThread
{
    Q_OBJECT

private:
    enum { MAXRECENTFILES = 7 };
    volatile bool stopped;            ///< переменная, контролирующая начало и конец выполнения потока
    QMutex mutex;                    ///< мьютекс для блокировки данных при работе с ними дополнительного потока

public:
    Reader::LogReader* logger;        ///< объект для чтения логов
    std::vector<LOGRECORD> read_log;///< вектор LOGRECORD , в котором находятся значения из считанного файла

protected:
    void run();

public:
    RThread(): stopped(false) {}
    void stop();
};

/// Запуск дополницельного потока
void RThread::run()
{
    forever
    {
        mutex.lock();
        if(stopped)
        {
            stopped = false;
            mutex.unlock();
            break;
        }
        read_log = logger -> TRead();
        mutex.unlock();
    }
    //QThread::run();
}

/// Остановка дополнительных потоков
void RThread::stop()
{
    mutex.lock();
    stopped = true;
    mutex.unlock();
}


Могу пояснить вопрос. Как вот в этом месте
if(delta > 5)
{
    rthread -> stop();
    //rthread -> wait(1000);
}

Перейти в функцию run()?

Сообщение отредактировал Litkevich Yuriy - 28.8.2008, 13:56
Причина редактирования: Добавлен тэг expand
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 4.2.2008, 20:06
Сообщение #2


Мастер
******

Группа: Модератор
Сообщений: 3291
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Если я тебя правильно понял, то rthread->start();

Но ИМХО лучше не в run передовать, а в какую-нибудь другую функцию данного потока посредством сигналов и слотов.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 4.2.2008, 20:15
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(ViGOur @ 4.2.2008, 20:06) *
Если я тебя правильно понял, то rthread->start();

Но ИМХО лучше не в run передовать, а в какую-нибудь другую функцию данного потока посредством сигналов и слотов.

ну да, правильно поняли. Как с помощью сигналов и слотов, если несложно, помогите, пожалуйста!!!

Сообщение отредактировал AD22 - 4.2.2008, 20:15
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 4.2.2008, 20:32
Сообщение #4


Мастер
******

Группа: Модератор
Сообщений: 3291
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Ну с сигналами и слотами все достаточно просто.

Создаем сигнал (threadSignal) и слот (threadSlot) и связываем их:
connect( this, SIGNAL( threadSignal), pObject, SLOT( threadSlot));

Разумеется их нужно обьявить в классе с ключевыми словами signals и slots. Для сигнала в moc файле быдет создано определение автоматически, для слота нужно будет писать самому, в принципе слот это обычная функция.

Затем, чтобы вызвать сигнал нужно написать:
emit threadSignal();

Еще нужно помнить, что слот threadSlot, будет выполнять в том потоке, в котором был создан pObject.
Вот в принципе и все.

Для лучшего понимая сигналов и слотов рекомендую прочитать: Сигналы и слоты.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 4.2.2008, 20:40
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(ViGOur @ 4.2.2008, 20:32) *
Ну с сигналами и слотами все достаточно просто.

Создаем сигнал (threadSignal) и слот (threadSlot) и связываем их:
connect( this, SIGNAL( threadSignal), pObject, SLOT( threadSlot));

Разумеется их нужно обьявить в классе с ключевыми словами signals и slots. Для сигнала в moc файле быдет создано определение автоматически, для слота нужно будет писать самому, в принципе слот это обычная функция.

Затем, чтобы вызвать сигнал нужно написать:
emit threadSignal();

Еще нужно помнить, что слот threadSlot, будет выполнять в том потоке, в котором был создан pObject.
Вот в принципе и все.

Для лучшего понимая сигналов и слотов рекомендую прочитать: Сигналы и слоты.

В принципе понятно, но а в каком классе, из приведенных выше, надо сделать connect, а в каких эти threadSlot, threadSignal? Что за pObject?

Сообщение отредактировал AD22 - 4.2.2008, 20:41
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 4.2.2008, 20:53
Сообщение #6


Мастер
******

Группа: Модератор
Сообщений: 3291
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Думаю, что в твоем варианте примерно так:
class LogReader: public QObject
{
   // ...
   LogReader();

protected signals:
   void threadSignal();

   // ...
};

LogReader::LogReader()
{
   // ...
   connect( this, SIGNAL( threadSignal), rthread, SLOT( threadSlot)); // разумеется rthread должен быть валидным.
}

class RThread: public QThread
{
   // ...

public slots:
   void threadSlot();

   // ...
};

void RThread::threadSlot()
{
   // Здесь что-то делается...
}
Ну и вызываешь emit threadSignal(); в том участке коде, что показывал в первом посте...

Сообщение отредактировал ViGOur - 4.2.2008, 20:54
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 5.2.2008, 10:02
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Спасибо за помощь! :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 5.2.2008, 11:35
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


АААА. Еще не все.
Сделал.
Выдает ошибку -
Error: Signals cannot have access specifier

Как избавиться. Нужно ли тело для threadSignal()?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 5.2.2008, 11:40
Сообщение #9


Мастер
******

Группа: Модератор
Сообщений: 3291
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Определение для сигнала не нужно, оно генерируется автоматически moc'ом.

В какой строчке выдает ошибку?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 5.2.2008, 11:46
Сообщение #10


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(ViGOur @ 5.2.2008, 11:40) *
Определение для сигнала не нужно, оно генерируется автоматически moc'ом.

В какой строчке выдает ошибку?

На строчки
protected signals:
        void threadSignal();

Естественно, есть макрос Q_OBJECT.

Сообщение отредактировал AD22 - 5.2.2008, 11:47
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

5 страниц V   1 2 3 > » 
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 9.7.2020, 7:30