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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: многопоточность, func arg  (Прочитано 8726 раз)
opera
Чайник
*
Offline Offline

Сообщений: 93


Просмотр профиля
« : Октябрь 05, 2020, 19:43 »

Добрый вечер, подскажите пожалуйста, у меня есть класс MyClass с функцией, которая должна осуществлять некоторые рассчеты:
Код:
void MyClass::calculationFunc(const QVector& list)
{
   for(int i = 0; i < list.size(); i++)
  {
          my work
  }
}
как мне вызывать функцию одного объекта MyClass obj в нескольких потоках, что-то типо:
Код:
for(int n = 0;  n < 3; n++)
{
     QThread* thread = new QThread(this);
     ......здесь не знаю что писать
}
то есть создавалось бы три потока, каждый из которых использовал объект MyClass , а именно функцию calculationFunc с переданными в нее аргументами, подскажите пожалуйста пример кода, спасибо!
Записан
tux
Global Moderator
Бывалый
*****
Offline Offline

Сообщений: 404



Просмотр профиля
« Ответ #1 : Октябрь 05, 2020, 20:19 »

https://code.qt.io/cgit/qt/qtbase.git/tree/examples/qtconcurrent/runfunction/main.cpp?h=5.15
Записан

opera
Чайник
*
Offline Offline

Сообщений: 93


Просмотр профиля
« Ответ #2 : Октябрь 05, 2020, 20:30 »


а именно с классами , функциями и объектами?Потому что в объекте много переменных и других объектов, которые как раз и используются в рассчете функции
« Последнее редактирование: Октябрь 05, 2020, 20:36 от opera » Записан
opera
Чайник
*
Offline Offline

Сообщений: 93


Просмотр профиля
« Ответ #3 : Октябрь 06, 2020, 10:17 »

Нашел вот такой способ:

Код:
class MyClass
{
public:
    MyClass()
    {

    }
    void hello(QString name, long long value)
    {
        int xx =_intValue;
        long long x = value;//2111111111;
        while(x)
            x--;
        qDebug() << "Hello" << name << "from" << QThread::currentThread();
    }
private:
    int _intValue = 4;
};

int main(int argc, char *argv[])
{

    QApplication a(argc, argv);
    MyClass class1;
    QFuture<void> f1 = QtConcurrent::run(&class1,&MyClass::hello, QString("Alice"), 2111111111);
    QFuture<void> f2 = QtConcurrent::run(&class1,&MyClass::hello, QString("Bob"), 3111111111);
    f1.waitForFinished();
    f2.waitForFinished();
return 0;
}
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #4 : Октябрь 06, 2020, 12:24 »

да, вам это и советовали. функцию лучше сделать константной, чтобы бить себе по рукам за попытку поменять данные класса из разных потоков (это можно, но нужен будет мьютекс)
Записан
opera
Чайник
*
Offline Offline

Сообщений: 93


Просмотр профиля
« Ответ #5 : Октябрь 06, 2020, 13:47 »

да, вам это и советовали. функцию лучше сделать константной, чтобы бить себе по рукам за попытку поменять данные класса из разных потоков (это можно, но нужен будет мьютекс)
спасибо, хороший совет)
Записан
opera
Чайник
*
Offline Offline

Сообщений: 93


Просмотр профиля
« Ответ #6 : Октябрь 06, 2020, 15:00 »

а как сделать, если я не знаю количества функций(зависит от количества ядер),но хочу использовать ожидание waitForFinished:
Код:
int count_thread = QThread::idealThreadCount()-1;
    QFuture <void> f;
    for(int i = 0; i < count_thread; i++)
    {
        f = QtConcurrent::run(_managerObj,&iManager::calcRebate, i);
    }
    f.waitForFinished();
использование вектора не удается
« Последнее редактирование: Октябрь 06, 2020, 15:32 от opera » Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #7 : Октябрь 06, 2020, 16:16 »

Код:
int count_thread = QThread::idealThreadCount()-1;
    std::vector<QFuture<void>> futures;
    futures.reserve(count_thread);
    for(int i = 0; i < count_thread; i++)
    {
        futures.push_back(QtConcurrent::run(_managerObj,&iManager::calcRebate, i));
    }
    for (auto &f: futures) // const auto?
         f.waitForFinished();
Записан
opera
Чайник
*
Offline Offline

Сообщений: 93


Просмотр профиля
« Ответ #8 : Октябрь 06, 2020, 17:10 »

Код:
int count_thread = QThread::idealThreadCount()-1;
    std::vector<QFuture<void>> futures;
    futures.reserve(count_thread);
    for(int i = 0; i < count_thread; i++)
    {
        futures.push_back(QtConcurrent::run(_managerObj,&iManager::calcRebate, i));
    }
    for (auto &f: futures) // const auto?
         f.waitForFinished();
спасибо!
Записан
opera
Чайник
*
Offline Offline

Сообщений: 93


Просмотр профиля
« Ответ #9 : Октябрь 08, 2020, 13:52 »

А можно ли было это же записать через map?Если да, то можно тоже кодовым примером?
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #10 : Октябрь 08, 2020, 14:36 »

А что ключом-то должно быть?
Записан
opera
Чайник
*
Offline Offline

Сообщений: 93


Просмотр профиля
« Ответ #11 : Октябрь 08, 2020, 14:40 »

А что ключом-то должно быть?
QtConcurrent::map() применяет функцию к каждому элементу в контейнере, изменяя элементы на месте - это из документации
соответственно контейнером должен быть QVector<int> listI
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #12 : Октябрь 08, 2020, 14:47 »

А, этот map =) я подумал об std::map.

типа такого? код не компилировал=)
Код:
int count_thread = QThread::idealThreadCount()-1;
    std::vector<i> tasks;
    tasks.reserve(count_thread);
    for(int i = 0; i < count_thread; i++)
    {
        tasks.push_back(i);
    }
    const auto future = QtConcurrent::map([&_managerObj](int i){ _managerObj->calcRebate(i); return i; }, tasks);
    future.waitForFinished();
Записан
opera
Чайник
*
Offline Offline

Сообщений: 93


Просмотр профиля
« Ответ #13 : Октябрь 08, 2020, 14:58 »

А, этот map =) я подумал об std::map.

типа такого? код не компилировал=)
Код:
int count_thread = QThread::idealThreadCount()-1;
    std::vector<i> tasks;
    tasks.reserve(count_thread);
    for(int i = 0; i < count_thread; i++)
    {
        tasks.push_back(i);
    }
    const auto future = QtConcurrent::map([&_managerObj](int i){ _managerObj->calcRebate(i); return i; }, tasks);
    future.waitForFinished();
да, что-то типо того, только хотелось бы разъяснение,что на каком месте идет, вижу лямбду

попытался передать два параметра(два списка), но не компилится:


Код:
QVector<QString> listStr;
    QVector<long long> listLong;
    auto future = QtConcurrent::map([&classObj](QString str,long long l){ classObj.incrCalc(str,l); return str; }, listStr,listLong);
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #14 : Октябрь 08, 2020, 15:05 »

Если вы передаете параметром vector<T> то функция маппера должна иметь вид T foo(const T&) - то есть берет старое значение и возвращает новое. Поэтому нужна лямбда чтобы сигнатура была "правильной". Возвращать можно то, что передали, или 0, не особо важно.
Два списка передать нельзя, надо их склеить в один список, например пар или структур.
отличие map от mapped что первый модифицирует контейнер inplace (перeписывая значения новым, "смапленным" значением) когда вторая - "возвращает" значения через список в самой QFuture
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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