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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: [РЕШЕНО] QFuture и QtConcurrent удаление потока после завершения фукнции  (Прочитано 10476 раз)
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« : Сентябрь 09, 2012, 19:59 »

Здравствуйте! Улыбающийся
Использую QFuture и QtConcurrent для того чтобы функция выполнялась в отдельном потоке и не нагружала главный
Написал тестовый вариант на основе примера QtConcurrent Run Function Example:
Код:
#include <QDebug>
#include <QThread>
#include <QString>
#include <QtConcurrentRun>
#include <QFuture>
#include <QApplication>

class foo
{
public:
    foo(QString str)
    {
        QtConcurrent::run(this, &foo::msg, str);
    }
private:
    void msg(QString name)
    {
        qDebug() << "Hello" << name << "from" << QThread::currentThread();
    }
};

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    foo("Hello World!");
    foo("Hello C++!");
    foo("Hello Qt!");

    app.exec();
}

только вот после выполнения не остается всего 1 поток - главный а весят 4

смотря в документацию изменил конструктор:
Код:
    foo(QString str)
    {
        QFuture <void> threadFunc = QtConcurrent::run(this, &foo::msg, str);
        threadFunc.waitForFinished();
        threadFunc.cancel();
    }
но не все созданные потоки можно закрыть (остаются не закрытыми 2: главный и созданный run), о чем, если я не ошибаюсь написанно в документации

в программе могут использоваться множество раз одни и теже функции:
Код:
void Note::loadDataNote()
{
    QSettings settingsINI(pathIni, QSettings::IniFormat);

    settingsINI.setIniCodec(QTextCodec::codecForName("windows-1251"));

    dataNote.globalPosX       = settingsINI.value("GlobalPosX", 100).toInt();
    dataNote.globalPosY       = settingsINI.value("GlobalPosY", 100).toInt();
    dataNote.width            = settingsINI.value("Width", 200).toInt();
    dataNote.height           = settingsINI.value("Height", 200).toInt();
    dataNote.title            = settingsINI.value("Title", "").toString();
    dataNote.lock             = settingsINI.value("Lock", false).toBool();
    dataNote.text             = settingsINI.value("Text", "").toString();
    dataNote.visible          = settingsINI.value("Visible", true).toBool();
    dataNote.opacityNote      = settingsINI.value("Opacity", 100).toFloat() / 100;
    dataNote.colorNote        = con.getColorFromHexColorForStyleSheet(color);
    dataNote.attribute        = settingsINI.value("Attribute", "Default").toString();
    dataNote.dateOfCreating   = settingsINI.value("DateOfCreating", date).toString();
    dataNote.dateLastChange   = settingsINI.value("DateLastChange", date).toString();
    dataNote.countTextSymbols = settingsINI.value("CountTextSymbols", 0).toInt();
    dataNote.countTextLines   = settingsINI.value("CountTextLines", 1).toInt();
    dataNote.password         = settingsINI.value("Password/Password", "").toString();
    dataNote.protectionActive = settingsINI.value("Password/protectionActive", false).toBool();
}

void Note::saveDataNote()
{
    QSettings settingsINI(pathIni, QSettings::IniFormat);

    settingsINI.setIniCodec(QTextCodec::codecForName("windows-1251"));

    settingsINI.setValue("GlobalPosX",        dataNote.globalPosX);
    settingsINI.setValue("GlobalPosY",        dataNote.globalPosY);
    settingsINI.setValue("Width",             dataNote.width);
    settingsINI.setValue("Height",            dataNote.height);
    settingsINI.setValue("Title",             dataNote.title);
    settingsINI.setValue("Lock",              dataNote.lock);
    settingsINI.setValue("Text",              dataNote.text);
    settingsINI.setValue("Visible",           dataNote.visible);
    settingsINI.setValue("Opacity",           int(dataNote.opacityNote * 100));
    settingsINI.setValue("Color",             color);
    settingsINI.setValue("Attribute",         dataNote.attribute);
    settingsINI.setValue("DateOfCreating",    dataNote.dateOfCreating);
    settingsINI.setValue("DateLastChange",    dataNote.dateLastChange);
    settingsINI.setValue("CountTextSymbols",  dataNote.countTextSymbols);
    settingsINI.setValue("CountTextLines",    dataNote.countTextLines);
    settingsINI.setValue("Password/Password", dataNote.password);
    settingsINI.setValue("Password/protectionActive", dataNote.protectionActive);

    settingsINI.sync();
}

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

как правильно запустить функцию в отдельном потоке, и после выполнения функции закрыть поток? Улыбающийся
« Последнее редактирование: Ноябрь 11, 2012, 20:28 от gil9red » Записан

mutineer
Гость
« Ответ #1 : Сентябрь 09, 2012, 20:02 »

Зачем закрывать? QtConcurrent следущую функцию запустит в одном из уже имеющихся потоков, чем сократит издержки на многократный запуск/остановку потоков
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #2 : Сентябрь 09, 2012, 20:09 »

Значит
Код:
        threadFunc.waitForFinished();
        threadFunc.cancel();

вызов функции в созданном потоке, если предыдущая функция завершилась или создание нового потока?
Записан

mutineer
Гость
« Ответ #3 : Сентябрь 09, 2012, 20:16 »

Значит
Код:
        threadFunc.waitForFinished();
        threadFunc.cancel();

вызов функции в созданном потоке, если предыдущая функция завершилась или создание нового потока?

Эти две строки имеют мало смысла - пытаться остановить вычисление тогда, когда оно уже остановилось это очень странно

Ну и даже если ты поменяешь их местами, то:
Цитировать
the future returned by QtConcurrent::run() cannot be canceled
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #4 : Сентябрь 09, 2012, 20:38 »

не без этих строчек количество поток с каждым вызовом run будет расти
Записан

mutineer
Гость
« Ответ #5 : Сентябрь 09, 2012, 20:39 »

не без этих строчек количество поток с каждым вызовом run будет расти
Ты пробовал? создай три задания, подожди пока они выполнятся, а потом задай еще 2-3. Сколько потоков будет?
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #6 : Сентябрь 09, 2012, 21:06 »

Вроде разобрался=)
не без этих строчек количество поток с каждым вызовом run будет расти
Ты пробовал? создай три задания, подожди пока они выполнятся, а потом задай еще 2-3. Сколько потоков будет?
1. Без строчек:
Код:
 QFuture <void> threadFunc = QtConcurrent::run(this, &foo::msg, str);
 threadFunc.waitForFinished();
 threadFunc.cancel();
и с 3 заданиями создаваться + 3 потока, если после выполнения этих трех заданий добавить, например + 2 задания, то они будут выполняться, но не будут создавать новые потоки


2. С строками:
Код:
 QFuture <void> threadFunc = QtConcurrent::run(this, &foo::msg, str);
 threadFunc.waitForFinished();
 threadFunc.cancel();
и с 3 заданиями создаваться + 1 поток, если после выполнения этих трех заданий добавить, например + 2 задания, то они будут выполняться, но не будут создавать новые потоки


код:
Код:
#include <QDebug>
#include <QThread>
#include <QString>
#include <QtConcurrentRun>
#include <QFuture>
#include <QApplication>
#include <QtGui>

class SleeperThread : public QThread
{
public:
    static void msleep(unsigned long msecs)
    {
        QThread::msleep(msecs);
    }
};

class foo
{
public:
    foo(QString str)
    {
        QFuture <void> threadFunc = QtConcurrent::run(this, &foo::msg, str);
        threadFunc.waitForFinished();
        threadFunc.cancel();
    }
private:
    void msg(QString name)
    {
        qDebug() << "Hello" << name << "from" << QThread::currentThread();
    }
};

void main(int argc, char **argv)
{
    QApplication app(argc, argv);

    foo("Hello World!");
    foo("Hello C++!");
    foo("Hello Qt!");

    SleeperThread::msleep(3000);

    foo("1");
    foo("2");

    app.exec();
}
Записан

mutineer
Гость
« Ответ #7 : Сентябрь 10, 2012, 01:07 »

Магия этих твоих двух строк (точнее одной - waitForFinished) в том, что код ждет выполнения текущего задания, прежде чем дать следующее. А раз задания выполняются точно одно за одним, то им достаточно одного дополнительного потока. Если завершения не ждать, то несколько заданий будут выполняться одновременно и им уже нужно больше потоков
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #8 : Сентябрь 10, 2012, 20:50 »

Ок Улыбающийся Смеющийся
Записан

fuCtor
Гость
« Ответ #9 : Сентябрь 16, 2012, 16:15 »

QtConcurrent использует для выполнения пул потов, который можно получить через QThreadPool::globaInstance(). Там то и указывается сколько максимально потоков может быть задействованно и другие параметры.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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