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

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

Страниц: 1 [2] 3 4   Вниз
  Печать  
Автор Тема: Опять потоки!  (Прочитано 27361 раз)
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #15 : Июнь 05, 2009, 16:02 »

Цитировать
ну а как иначе то?

Как иначе? Вызвать execMethod в run

 Я понимаю что так надо сделать! Но мне это не подходит! Улыбающийся

Цитировать
void execMethod() {}
QFuture<void> QtConcurrent::run (execMethod)

у мну QT 4.1.1 Улыбающийся

ну вы как не понимаете!

Мне нужно извне запускать методы так, чтобы они выполнялись в другом потоке!

т.е вызываю метод к примеру mWrite(data) - он шлет сигнал в замерший на exec() поток, в котором выполняется слот (например) QIODevice::write(data)

ну и т.п. в том же духе!!! Улыбающийся
Записан

ArchLinux x86_64 / Win10 64 bit
ритт
Гость
« Ответ #16 : Июнь 05, 2009, 16:59 »

всё мы понимаем.
и понимаем, что всё это глупо.

1. invokeMethod
2. QCustomEvent
3. шедуль вызова метода через межпотоковую синхронизацию (mutex/semaphore/waiter/etc.)
последний метод удобен для конкурентных вызовов, когда может образовываться "упорядоченная очередь выполнения" (с приоритетами, распараллеливанием и т.д.)

упд.: к тому же, для третьего варианта можно обойтись и без петли (ну, мало ли? - вдруг кто петель боится?) - посмотреть можно в QFileInfoGatherer (или как-то так)...
« Последнее редактирование: Июнь 05, 2009, 17:02 от Константин » Записан
MoPDoBoPoT
Гость
« Ответ #17 : Июнь 05, 2009, 17:16 »

tc->moveToThread(tc)
Поток Клейна прямо какой-то  Улыбающийся
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #18 : Июнь 05, 2009, 18:07 »

Я так понимаю всё это должно появится в "библиотеке для работы с последовательными портами"
Только вот "Мне нужно извне запускать методы так, чтобы они выполнялись в другом потоке!" по моему разумению совсем ненужно запускать разные методы. Нужно из потока последовательного порта сигналы слать и всё.
Записан

Юра.
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #19 : Июнь 05, 2009, 18:12 »

скажите, а если реализовать так как я запостил в этой теме пост №2 - так можно?
Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #20 : Июнь 05, 2009, 18:50 »

2  lit-uriy,

не, в библиотеке уже ничо нового не будет Улыбающийся - но суть примерно уловили.. и это только вершина айсберга моей задумки Улыбающийся

В общем , если говорить по простому, я задумал сделать нечто, использующее и в том числе и эту библиотеку....
Идею объясняю на примере: (только, товарищи программисты просьба абстрагироваться от программирования Улыбающийся )
1. нужно создать некий класс А, который выполнял бы функцию опроса, записи, и чтения данных из некоего устройства
2. этот класс А для других классов X, Y, Z должен являться "черным ящиком",
3. эти другие классы могут извне управлять классом А (т.е посылать команды) посредством некоего API. Это API пусть представляют из себя два публичных метода класса A
Код:
class A 
{
....
public:
    m_readdata(набор неких параметров);
    m_writedata(набор неких параметров)
}
- эти методы являются по сути просто неким не зависящим от протокола обмена данными интерфейсом. т.е любой сторонний класс чтобы отправить или прочитать данные из класса A просто должен вызвать эти методы.
- эти методы при вызове эмиттяд соответственно сигналы
Код:
class A
{
...
signals:
    sigReaddata(параметры)
    sigWritedata(параметры)
....
}
4. далее.. внутри класса A должна быть запущена нить, в которой с помощью методов класса B (этот класс В  может быть и классом для работы с последова тельными портами и также и сокетом) происходит следующее:
 а) постоянно по таймеру происходит опрос некоего у-ва при помощи методов класса В (например B::read(парам)) и прочитанные данные складываются в некие обрасти памяти класса A
 б) должны отлавливаться сигналы sigReaddata(параметры) и sigWritedata(параметры) и соответственно им вызываться опять же методы класса B::read(параметры) B::write(параметры) которые должны выполняться в нити в которой выполняется и опрос у-ва . Эти методы класса В уже привязаны к определенному протоколу обмена.. т.е форматы передаваемых и приниваемых кадров специфические
----------------------------------------

защищать друг от друга методы B::read(парам)  и B::write(парам) я пока решил мьютексами.

Хочется подчеркнуть, что методы B::read(парам)  и B::write(парам) являются транзакциями, т.е метод B::read(парам) отправляет данные удаленному узлу.. потом ждет пока придет ответ, читает ответ и декодирует его и результат сохраняет в классе A// Аналогично и метод ::write(парам)

В итоге должно получиться так, что методы класса A должны выполняться в своем потоке.. а методы класса В в своем.. связь между ними пока я думаю сигналами сделать...

т.е от методов класса А -> через сигналы -> к методам (слотам) класса В

----------------------

итого, если смотреть мой пост №2 то под классом А можно принять - класс ThreadClass а под классом В - класс PrintClass

В принципе думаю такая идея имеет право на существование.. или может быть посоветуете другую идею как такое реализовать?

 
Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #21 : Июнь 05, 2009, 19:35 »

Мне вот что не понятно, почему ты все это хочешь запихать в класс-насследник от QThread?
Можно же в самих методах m_readdata и m_writedata создавать и запускать необходимые нити, связывать их с нужными сигналами/слотами.
Всю реализацию скрыть от конечного пользователя за интерфейсом.
IMHO, с точки зрения архитектуры так будет правильней и логичней.
Записан
ритт
Гость
« Ответ #22 : Июнь 06, 2009, 09:47 »

дополню пост BRE - есть такая вещь как thread pool
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #23 : Июнь 06, 2009, 15:56 »

Цитировать
Мне вот что не понятно, почему ты все это хочешь запихать в класс-насследник от QThread?
ну чтобы не городить лишнего Улыбающийся....
т.е в приват класса А (который наследник QThread)  запихнуть указатель на класс В (в котором имеются публичные методы-слоты для чтения/записи устройства) ... сам класс В создавать в методе run класса А и коннектится там же.. а потом вызвать exec
что-то вроде:

Код:
class A : public QThread
{
    Q_OBJECT
public:
    m_read() { emit s_read(); }
    m_write() { emit s_write(); }
signals:
    s_read();
    s_write();
protected:
    run();
private:
   ClassB *B;
}

A : :run() {
    B = new ClassB;
    connect(this, s_read(), B, slotTransactionRead());
    connect(this, s_write(), B, slotTransactionWrite());
    ....
    exec();
}
....

Цитировать
Можно же в самих методах m_readdata и m_writedata создавать и запускать необходимые нити, связывать их с нужными сигналами/слотами.
например ? код пжлста! Улыбающийся

Цитировать
дополню пост BRE - есть такая вещь как thread pool
я не нашел такого что-то
Записан

ArchLinux x86_64 / Win10 64 bit
ритт
Гость
« Ответ #24 : Июнь 06, 2009, 16:04 »

http://doc.trolltech.com/main-snapshot/qthreadpool.html
Записан
BRE
Гость
« Ответ #25 : Июнь 06, 2009, 16:21 »

Например так:
Код
C++ (Qt)
class A : public QObject
{
   Q_OBJECT
public:
   void m_read()
   void m_write()
 
private:
   ClassB *B;
};
 
void A::m_read()
{
   ThreadRead *th = new ThreadRead();
   connect( th, s_read(), B, slotTransactionRead() );
   th->start();
}
 

Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #26 : Июнь 06, 2009, 16:40 »

2 BRE,

1 . но в вашем примере кто будет эмиттить сигнал s_read() Непонимающий и как вообще?
2. зачем городить огород и еще и описывать помимо классов А и В еще и класс th ?
3. не уверен что слот slotTransactionRead выполнится в потоке th . нужно проверить
Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #27 : Июнь 06, 2009, 16:45 »

2 BRE,

1 . но в вашем примере кто будет эмиттить сигнал s_read() Непонимающий и как вообще?
2. зачем городить огород и еще и описывать помимо классов А и В еще и класс th ?
3. не уверен что слот slotTransactionRead выполнится в потоке th . нужно проверить
Клиент вызывает метод m_read, он запускает отдельную нить (ThreadRead) на чтение данных, когда данные будут готовы, нить посылает сигнал s_read, о том что данные готовы к использованию. Кто будет отлавливать сигнал s_read решает клиент. Данные читаются и готовятся в отдельном потоке.
Опять же клиент может одновременно запустить отдельные нити на чтение и на запись.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #28 : Июнь 06, 2009, 17:17 »

Цитировать
Клиент вызывает метод m_read, он запускает отдельную нить (ThreadRead) на чтение данных, когда данные будут готовы, нить посылает сигнал s_read, о том что данные готовы к использованию.
1. Метод m_read должен содержать параметры...  т.е m_read(параметры) !  Эти параметры должны передаваться в поток (например классу B)
   Как в вашем примере это реализовать?
2. Чтениеданных должны выполнять методы класса В которые должны принять на вход параметры от m_read(параметры) и уже в зависимости от того что за параметры - эти методы будут создавать соответствующие запросы удаленным узлам
3. Мне не нужно чтобы поток емиттил сигналы Улыбающийся
4. Прочитанные данные поток (методы класса В) должен положить в массивы данных класса А
5. Методы класса В (который выполняется в другом потоке)  должны всегда опрашивать удаленные узлы (по порядку например) если в конфиге узла имеется к примеру флаг ( automaticPoll=true).
6. В методах класса А :  m_read(парам) и m_write(парам) одним из параметров является флаг например manual=true...
- если manual=true, то значит метод m_read(парам) емиттит сигнал в поток , и передает туда параметры - типа какой узел нужно прочитать и т.п. и далее уже читает не сами данные, которые прочитали методы класса B - а данные которы уже готовые хранятся в массивах класса А
- если manual=false - то значит что метод m_read(парам) не будет эммитить сигнал в поток.. а сразу прочитает готовые данные в массивах класса А, т.е подразумевается, что поток и так в автоматическом режиме уже читает эти узлы!  Улыбающийся

Вот как то так

« Последнее редактирование: Июнь 06, 2009, 17:20 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #29 : Июнь 06, 2009, 18:52 »

т.е в общих чертах привожу код
вот примерно так должно выглядеть было: (к примеру)

Код:
class B : public QObject
{
Q_OBJECT
public slots:
void slotReadFromNode(int nodeAddress, int startDataAddress, int quantityData) {
/*
1. Читает данные из удаленного узла
2. Сохраняет их в dataNode1 или dataNodeN в зависимости от адреса узла и т.п.
*/
}
void slotWriteToNode(int nodeAddress, int startDataAddress, int quantityData , QByteArray &data) {
/*
выполняется отправка данных в удаленный узел и ожидание положительной квитанции от узла
*/
}
void pollingNodes() {
for (i=0;i<N;i++) { //выполняется опрос всех узлов
slotReadFromNode(int nodeAddress, int startDataAddress, int quantityData, const QByteArray &data);
}
}
public:
QByteArray readReadyData(int nodeAddress, int startDataAddress, int quantityData) {
QByteArray data;
switch (nodeAddress) {
case 1:
data = dataNode1;
//тут из массива data вырезаем кусок от startDataAddress до startDataAddress+quantityData
break;
case N:
data = dataNodeN;
//тут из массива data вырезаем кусок от startDataAddress до startDataAddress+quantityData
break;
}
return data;
}
//массивы готовых данных
QByteArray dataNode1;
QByteArray dataNode2;
.....................
QByteArray dataNodeN;
/*
где:
nodeAddress - адрес запрашиваемого удаленного узла
startDataAddress - стартовый адрес данных которые нужно или прочитать или записать
quantityData - количество байт данных которые нужно записать или прочитать (по порядку)
data - сами данные
*/
}

class A : public QThread
{
Q_OBJECT
signals:
void s_readData(int nodeAddress, int startDataAddress, int quantityData, QByteArray &data);
void s_writeData(int nodeAddress, int startDataAddress, int quantityData, const QByteArray &data);
public:
void m_readData(int nodeAddress, int startDataAddress, int quantityData, QByteArray &data, bool manual) {
if (manual) emit s_readData(nodeAddress, startDataAddress, quantityData, data);
data = cb->readReadyData(nodeAddress, startDataAddress, quantityData);
}
void m_writeData(int nodeAddress, int startDataAddress, int quantityData, const QByteArray &data, bool manual) {
if (manual) emit s_writeData(nodeAddress, startDataAddress, quantityData, data);
}
protected:
void run() {
cb = new B;
connect(this, SIGNAL(s_readData(парам)), cb, SLOT(slotReadFromNode(парам)));
connect(this, SIGNAL(s_writeData(парам)), cb, SLOT(slotWriteToNode(парам)));
QTimer timer;
connect(timer, SIGNAL(timeout()), cb, SLOT(pollingNodes()));
timer->start(1000);
exec();
}
private:
B* cb;
}


вот как то так по идее задумывалось! Улыбающийся
Записан

ArchLinux x86_64 / Win10 64 bit
Страниц: 1 [2] 3 4   Вверх
  Печать  
 
Перейти в:  


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