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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Поток ГУИ и другой поток с циклом while  (Прочитано 6004 раз)
crashtua
Гость
« : Апрель 28, 2011, 12:09 »

Есть у нас главный поток с ГУИ, есть другой поток, в котором запущена одна штука, которая работает через безконечный цикл while. Как передать данные из ГУИ в тот поток, если он постоянно знят? Какими средствами можно сделать типа такого:в потоке ГУИ создаем очередь сообщений, а в другом потоке в цикле  while мы их забираем из потока ГУИ?
Записан
BRE
Гость
« Ответ #1 : Апрель 28, 2011, 12:12 »

http://www.prog.org.ru/topic_14426_0.html
Записан
crashtua
Гость
« Ответ #2 : Май 01, 2011, 18:22 »

Остановился на варианте
Код:
class MessageStack
{
    QReadWriteLock lock;
    QStack<QString> stack;
public:
    QString i;
    int get()
    {
    lock.lockForRead();
i = stack.pop();
lock.unlock();
return i;
    }
    void add(int i)
    {
lock.lockForWrite();
list.push(i);
lock.unlock();}
};
Другой не ГУИ потом будет считывать данные с частотой 50 и выше милисекунд. ГУИ поток будет записывать с скоростью от 10 до бесконечности:). Если допустим, ГУИ поток будет писать значение, а другой поток попробует считать, то как будет вести себя вся конструкция? Другой поток подождет ГУИ поток?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Май 01, 2011, 19:32 »

Остановился на варианте
Ну варианта пока нет - это Вы защитили данные, а надо еще синхронизировать запись/чтение. Можно напр так
Код
C++ (Qt)
class MessageStack
{
   QReadWriteLock lock;
   QStack<QString> stack;
   QSemaphore mSemaphore;
public:
   QString i;
   int get()
   {
       mSemaphore.acquire();  // ждем когда можно забрать данные
    lock.lockForRead();
i = stack.pop();
lock.unlock();
return i;
   }
   void add(int i)
   {
lock.lockForWrite();
list.push(i);
lock.unlock();
       mSemaphore.release();  //  теперь get может забирать  
   }
};
Записан
andybeg
Гость
« Ответ #4 : Май 01, 2011, 20:00 »

мне многое открыла бланшет, там про ЭТО есть Улыбающийся
Бланшет,Саммерфилд - QT4 Программирование GUI на С++.2ed.2008.djvu
Записан
crashtua
Гость
« Ответ #5 : Май 01, 2011, 20:27 »

Igors, а как add знает, что в данный момент get не забирает меседж??
Записан
crashtua
Гость
« Ответ #6 : Май 01, 2011, 20:27 »

мне многое открыла бланшет, там про ЭТО есть Улыбающийся
Бланшет,Саммерфилд - QT4 Программирование GUI на С++.2ed.2008.djvu
почитаем, спасибо.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Май 02, 2011, 10:38 »

Igors, а как add знает, что в данный момент get не забирает меседж??
Он и не знает, просто ждет на локе, т.е. это задача блокировки. Кстати: QReadWriteLock здесь не подходит т.к. 2 или более ниток не могут одновременно делать pop (это не "чтение"). Поэтому замените его на обычный мутекс
Записан
crashtua
Гость
« Ответ #8 : Май 02, 2011, 13:53 »

Может быть так:
Код:
#pragma once
#include <QStack>
#include <QMutex>
#include <QString>
class GHQtCommandStack
{
public:
GHQtCommandStack(void);
~GHQtCommandStack(void);
QString get();
void add(QString str);
private:
QMutex mutex;
QStack<QString> stack;
};
Код:
#include "GHQtCommandStack.h"
GHQtCommandStack::GHQtCommandStack(void)
{
}
GHQtCommandStack::~GHQtCommandStack(void)
{
}
QString GHQtCommandStack::get()
{
QString result;
mutex.lock();
if(stack.isEmpty()){
mutex.unlock();
return "empty";
}
else
{
result=stack.pop();
mutex.unlock();
return result;
}
}
void GHQtCommandStack::add(QString str)
{
mutex.lock();
stack.push(str);
mutex.unlock();
}
Кстати, в данной ситуации, get() выполняется только нитью, которая создала GHQtCommandStack, а add() ГУИ нитью, и больше их не планируется, но все равно, хотелось бы все нюансы узнать...
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Май 02, 2011, 14:59 »

Может быть так:
Зависит от того что надо. Так у Вас нитка "ничего не ждет" - это разумно если ей есть еще чем заниматься, а иначе она будет крутиться на get и бестолково жечь процессор. Также возврат "empty" не выглядит хорошо (как потом ее отличить от "реальной" строки?), лучше немного изменить get. Также с QMutexLocker (вместо lock/unlock) будет заметно короче.

Кстати, в данной ситуации, get() выполняется только нитью, которая создала GHQtCommandStack, а add() ГУИ нитью, и больше их не планируется, но все равно, хотелось бы все нюансы узнать...
Как правило "используя допущения задачи" выиграть/сэкономить ничего не удается. Multi-thread конструкция либо работает для любого числа ниток - либо не работает вообще.
Записан
crashtua
Гость
« Ответ #10 : Май 02, 2011, 16:38 »

нитка "ничего не ждет"
Тоесть если mutex уже залочен то get ничего не обработает? А как заставить нитку ждать? А про возврат "empty"-формат строк используемый приложением своеобразный, в каждой "правильной" строке первым идет символ "!", так что переделывать get буду в самом конце...
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Май 02, 2011, 18:03 »

Тоесть если mutex уже залочен то get ничего не обработает? А как заставить нитку ждать?
Если мутекс захвачен (одной из ниток), то все остальные (что пытаются его получить) будут ждать. В Вашем случае мутекс захватывается на очень короткое время (push/pop) поэтому просто так крутить get в цикле while нехорошо. Поставьте waitCondition или семафор (см. пример выше).
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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