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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Передача объекта в несколько тредов  (Прочитано 3801 раз)
id2606
Гость
« : Август 31, 2012, 17:50 »

Добрый день!

Уже прочитал кучу статей, но так и не дошло как это реализовать:

Начну попорядку:

Есть
Код
C++ (Qt)
   class ChatModule : public WebModule
   {
   public:
       ChatModule(QString handle, QString password, QString logDir);
 
       virtual int checkNewRequest ();
       virtual int openChat();        
       virtual int getChatMessage();
       virtual int sendChatMessage(msg);
 
       UserAgent ua;
   };
 
 
 
Упростил функции очень сильно, но суть главная осталась,
класс UserAgent ничто иное как обычный HTTP клиент, причем СИНХРОННЫЙ, который использует QNetworkAccessManage;

Код
C++ (Qt)
   class UserAgent: public QObject
   {
   public:
       QNetworkAccessManager *m_nam;
       UserAgent(QString handle);
       virtual ~UserAgent();
 
       int get (QString url)
       {
           QEventLoop loop;
           reply = m_nam->get (req);
           connect (reply, SIGNAL(finished()), &loop, SLOT(quit()));
           loop.exec();
       }
 
   };
 
 
 

сам поток

Код
C++ (Qt)
   class ChildThread : public QThread
   {
   public:
 
       enum Statuses {statusOpen=0, statusCheck};
 
       ChildThread (ChatModule *module)
       {
           m_chat = module;
           m_chat->logMsg("Child create");
       }
 
       virtual ~ChildThread ()
       {
           m_chat->logMsg ("delete child");
       }
 
 
       virtual void run()
       {
           int status = 0;
 
           while (true)
           {
               if (status == ChildThread::statusOpen)
               {
                   if(m_chat->openChat())
                       status = ChildThread::statusCheck;
                   else
                       break;
               }
 
               if (status == ChildThread::statusCheck)
               {
                   if (m_chat->getChatMessage())
                   {
// Obrabotka
                   }
 
               }
 
               m_chat->logMsg("Sleep SLEEP_TIME sec");
               QEventLoop loop;
               QTimer::singleShot( SLEEP_TIME * 1000, &loop, SLOT( quit() ));
               loop.exec();
           }
 
 
           m_chat->logMsg("Child end.");
       }
 
   private:
       ChatModule *m_chat;
   };
 
 
 
главная тело программы
Код
C++ (Qt)
   ChatModule chatModule("username", "password", "logDir");
 
   chatModule.login ();
 
   while (true)
   {
      if (chatModule.checkNewRequest ())
      {
                   ChildThread *thread = new ChildThread(&chatModule);
                   thread->connect (thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
                   thread->start();
 
       }
   }
 
 
 
 
после старта вижу
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNetworkAccessManager(0x3e55c8), parent's thread is QThread(0x3e3e50)
, current thread is QThread(0xc8a118)


Причем это валится когда я пытаюсь сделать
Код
C++ (Qt)
   ChatModule::openChat {} { ua->get("blablalba"); }
 


Через некоторое время

ASSERT failure in QEventLoop::exec(): "internal error", file kernel/qeventloop.c
pp, line 225


Вопрос: как передать объект chatModule в НЕСКОЛЬКО тредов ?

Проблемы синхронизации контента решены в самом модуле UserAgent с помощью мутексов.
Записан
Bepec
Гость
« Ответ #1 : Август 31, 2012, 21:06 »

Ну начну издалека - зачем вам несколько чат клиентов работающих синхронно на одной машине? Улыбающийся

А проблема у вас в том, что Cannot create children for a parent that is in a different thread.
Записан
id2606
Гость
« Ответ #2 : Август 31, 2012, 22:30 »

Мне нужно не несколько чат клиентов а 1

Просто интрефейс для чата через http

В главном потоке я рефрешу страницу в поисках нового запроса на чат, потом запрещаю его или разрешаю.
Если я его разрешил, то тогда я запускаю чилд тред и он уже начинает обрабатывать сообщение от пользователя например User1.

Если в главном цикле приходит еще один запрос на разговор и я хочу с ним говорить, тогда я запускаю еще один тред в котором обрабатываю сообщения от User2 и отвечаю ему.

Вот как-то так (:
Записан
andrew.k
Гость
« Ответ #3 : Август 31, 2012, 23:51 »

Один пользователь - один поток. 1000 пользователей - 1000 потоков.
Уже много раз обсуждалось, что это плохое проектирование.
Поток это экземпляр оригинального класса QThread без всякого наследования.
Делаешь оптимальное число потоков (разное для разных машин, + в зависимости от нагрузки, например по 1000 клиентов на поток), т.е. нужное число экземпляров QThread.
Делаешь необходимое количество экземпляров ChatModule (на сколько я понял). Дальше должен быть некий менеджер который эти экземпляры будет ровным слоем распихивать (moveToThread) по имеющимся потокам.
Тогда твои экземпляры будут работать в нескольких потоках и не будет тьма потоков.
Записан
andrew.k
Гость
« Ответ #4 : Август 31, 2012, 23:52 »

поищи на форуме или в гугле тему про правильное использование QThread.
Записан
id2606
Гость
« Ответ #5 : Сентябрь 01, 2012, 01:49 »

Про правильное использование тредов я уже все прочитал, но не хватает мозгов по организации этого всего.
Я не понимаю как в Qt Это правильно сделать.

Может быть поможете с простой реализацией этого.

Объясняю задачу популярно:
Я залогинился на сайт через http
дошел до страницы с чатом (чат только приватный) и постоянно её рефрешу. Если есть запрос на чат я должен сделать следующее:
Распарсить юзера и его токен (нечто уникальное типа сессии). Я это делаю.
Потом я должен сделать запрос определенной страницы с этим токеном.

Распарсить результат и запрашивать третью страницу с сообщениями. Причем я это должен делать ну как минимум раз в 10 секунд. А дальше реагировать на них т.е. отвечать человеку который мне написал.

поэтому решил сделать так.

В главном цикле я запрашиваю страницу с запросами на чат от пользователей. Если есть новый запрос:

1 По своему, я запускают тред передаю туда свой ChatModule (т.к. запросы через NetworkAccessManager в нем хранятся куки авторизации я не могу создать новый объект т.к. потеряю куки и меня выкинет с сайта.)
И Дохожу до сообщений я постоянно начинаю их запрашивать и обновлять у клиента. Как только чат будет закрыт либо с моей стороны либо со стороны клиента я завершу тред и все.
Но в это время я в главном цикле постоянно проверяю сайт на НОВЫЕ запросы, если все устраивает повторяю пункт 1.

2. Как это реализовать без тредов ? Приведите пример пожалуйста.
Записан
id2606
Гость
« Ответ #6 : Сентябрь 01, 2012, 07:34 »

Решил в корне все изменить, теперь эта тема тут http://www.prog.org.ru/topic_22931_0.html
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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