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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как правильно вызвать метод из наследника QThread?  (Прочитано 4461 раз)
Myav
Гость
« : Декабрь 24, 2006, 19:57 »

Целый день бьюсь над проблемой:

Имеется клиент-серверное приложение. Наследник QTcpServer'а хранит в QMap<QString, Thread*> имена подключившихся пользователей и указатели на обслуживающие их нити.

Как только "правильность" подключившегося пользователя подтверждается, обслуживающая нить (наследник QThread'а) эмитит сигнал clientVerificationDone(QString userName, Thread* thread). Сигнал перехватывает сервер и добавляет пару имя/пользователя в QMap.

Беда в том, что иногда нужно передать сообщение от одного пользователя другому... Сейчас реализовано так:

получив сообщение от конечного пользователя нить эмитит сигнал messageSended(QByteArray from, QString to, QByteArray message); сигнал обрабатывается сервером в методе forwardMessage(). В методе мы находим указатель на нить получателя и вызываем метод этой нити, который и отсылает сообщение:

Код:
void Server::incomingConnection(int socketDescriptor)
{
Thread *thread = new Thread(socketDescriptor, this);
/* ... */
connect(thread, SIGNAL(messageSended(QByteArray, QString, QByteArray)), SLOT(forwardMessage(QByteArray, QString, QByteArray)), Qt::DirectConnection);
/* ... */
}


Код:
void Server::forwardMessage(QByteArray from, QString to, QByteArray message)
{
if (threads.contains(to))
threads[to]->sendMessage(from, message);
}


Проблема в том, что таким образом конечный пользователь может отослать сообщение только сам себе...

forwardMessage() будет запущен в потоке отправителя, а внутри вызывается метод из потока получателя Грустный

Можно как-нибудь явно вызывать threads[to]->sendMessage(from, message) из потока threads[to]?

Или может есть другой метод решения проблемы?
Записан
Dendy
Гость
« Ответ #1 : Декабрь 24, 2006, 21:22 »

У вас архи-неверньІй подход к решению задачи. Во первьІх не стоит на каждое подключение вьІделять один поток. Во вторьІх отправка сообщения через сигнальІ может привести к потере сообщения, если получатель уничтожится. В третьих, вьІ же не собираетесь создавать на каждьІй тип пакета свой сигнал! Поток и сокет - всего лишь транспортная система для получения данньІх. Их вьІборкой, анализом и обработкой поток сокета заниматься не должен. Тяжёлая логика, такая как передача сообщения пользователю/пользователям/в оффлайн/с фильтрацией на матьІ/и т.п. должна бьІть вьІнесена за передельІ транспортной системьІ.

Пользуйтесь postEvent() со своим типом собьІтия, в котором будет лежать пакет. Из потока с сокетом и в поток с сокетом. Различайте пользователей по идентификаторам. Другой вариант - используйте в потоке менеджер для сокетов как шлюз, что будет принимать пакетьІ через потокобезопастньІе методьІ и асинхронно отдавать их сокетам.

Вообще длинная тема.
Записан
Myav
Гость
« Ответ #2 : Декабрь 25, 2006, 04:17 »

Dendy, спасибо за ЦУ. Буду разбираться :shock:
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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