Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: gil9red от Сентябрь 04, 2012, 17:18



Название: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: gil9red от Сентябрь 04, 2012, 17:18
Здравствуйте!
Есть у меня 2 таблицы QTableWidget
Есть две функции заполняющие эти таблицы и выделяющие память под пользовательские виджеты
таблицы хранят информацию по пользовательским виджетам (наследование QWidget)

и если данных много, интерфейс начинает виснуть, что не хорошо
сначало решил воспользоваться QThread и передавать ему указатель на функцию, которую он будет в run() запускать, потом нашел информацию о QFuture и QtConcurrent

Теперь о главном, как запустить в двух потоках отдельные функции-члены, запуск нужно сделать в конструкторе класса, кроме того эти функции-члены принадлежат этому же классу

долго мучился, искал, потом тыкал пальцем в небо, и сгенерировал такой пример (который конечно не пашет, иначе не создавал здесь тему):
Код:
MyClass::MyClass(QWidget *parent):QWidget(parent)
{
 QFuture <void> threadLoadInTable1;
 QFuture <void> threadLoadInTable2;

 threadLoadInTable1 = QtConcurrent::run(&MyClass::loadInTable1);
 threadLoadInTable2 = QtConcurrent::run(&MyClass::loadInTable2);
}

Ошибка: no matching function for call to 'run(void (MyClass::*)())'

пытался так:
Код:
threadLoadInTable1 = QtConcurrent::run(loadInTable1);
Ошибка такая: no matching function for call to 'run(<unresolved overloaded function type>)'

прототипы для этих функций такого вида:
Код:
void function(void)
т.е. ничего не возвращают и параметры не принимают

Слышал, что gui нельзя создавать вне главного потока, и похоже все равно не получится запустить эти функции в отдельном потоке

Помогите пожалуйста!


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызов&
Отправлено: mutineer от Сентябрь 04, 2012, 17:31
Вместо тыканья пальцем куда ни попадя, лучше бы доку почитал...
http://doc.crossplatform.ru/qt/4.7.x/qtconcurrentrun.html#using-member-functions


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: kuzulis от Сентябрь 04, 2012, 17:34
См:

QtConcurrent Image Scaling Example
QtConcurrent Progress Dialog Example
QtConcurrent Run Function Example


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: gil9red от Сентябрь 04, 2012, 17:39
Читал уважаемый mutineer, и использовал для проверки такой код:
Код:
#include <QtGui/QApplication>
#include <QDebug>
#include <QtConcurrentRun>
#include <QFuture>

void func()
{
        for(int i = 0; i < 10; i++)
            qDebug() << i;
}

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

    QFuture <void> future = QtConcurrent::run(func);

    return a.exec();
}


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: mutineer от Сентябрь 04, 2012, 17:41
Читал уважаемый mutineer, и использовал для проверки такой код:

И секцию под названием Using Member Functions, на которую я линку дал, читал? Твой проверочный код к ней отношения не имеет


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: kuzulis от Сентябрь 04, 2012, 17:47
У меня пример компилится и работает!


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: gil9red от Сентябрь 04, 2012, 17:52
Читал уважаемый mutineer, и использовал для проверки такой код:

И секцию под названием Using Member Functions, на которую я линку дал, читал? Твой проверочный код к ней отношения не имеет
Я знаю, потому что тоже читал это :)

Уважаемый kuzulis, предоставленные вами названия примеров, кроме QtConcurrent Image Scaling Example, не имеют отношения к моему вопросу. Да и в QtConcurrent Image Scaling Example показывают только QFutureWatcher, который вряд ли поможет в решении проблемы


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: gil9red от Сентябрь 04, 2012, 17:53
У меня пример компилится и работает!
У меня ос windows xp, qt 4.8.0, minGW


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: mutineer от Сентябрь 04, 2012, 17:53
Читал уважаемый mutineer, и использовал для проверки такой код:

И секцию под названием Using Member Functions, на которую я линку дал, читал? Твой проверочный код к ней отношения не имеет
Я знаю, потому что тоже читал это :)

Тогда почему в коде, приведенном в первом посте, ты первым аргументом в run не передаешь указатель или ссылку на объект?


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: gil9red от Сентябрь 04, 2012, 17:55
разве не ссылка указана?
Код:
threadLoadInTable1 = QtConcurrent::run(&MyClass::loadInTable1);


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: mutineer от Сентябрь 04, 2012, 17:58
разве не ссылка указана?
Код:
threadLoadInTable1 = QtConcurrent::run(&MyClass::loadInTable1);

Указан адрес функции, который должен быть вторым параметром, а первым должен быть указатель или константная ссылка на объект

Цитировать
The first argument must be either a const reference or a pointer to an instance of the class


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: gil9red от Сентябрь 04, 2012, 18:03
Все разобрался, код такой:
Код:
QFuture <void> threadLoadInTable1 = QtConcurrent::run(this, &MyClass::loadInTable1);
Не знаю почему, писал сначала так:
Код:
QFuture <void> threadLoadInTable1 = QtConcurrent::run(MyClass, &MyClass::loadInTable1);

И потвердил свои сомнения, в консоль выдается такое:
QPixmap: It is not safe to use pixmaps outside the GUI thread
QObject::setParent: Cannot set parent, new parent is in a different thread


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: mutineer от Сентябрь 04, 2012, 18:08
Для ускорения заполнения таблицы попробуй перейти на model/view


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: gil9red от Сентябрь 04, 2012, 18:15
Да не из-за таблицы, я думаю виснет интерфейс, а из-за выделения памяти и создания виджетов, в таблицах ведь каждая строка - один виджет, каждый виджет тратит на себя где-то 0.3мб, а ведь ему еще нужно загрузить еще свои данные, вот и виснет :)

Есть вариант создавать эти виджеты в качестве отдельного процесса, но это будет не красиво (да и сработает ли вообще??), представьте если будет этих виджетов 50 или более..

Для ускорения заполнения таблицы попробуй перейти на model/view
Интерфейс виснет уже когда более 20 записей (20 виджетов) в таблице, от перехода ситуацию не изменится :)

Можно, конечно, сделать отправление сигналов из потоков в главный поток типа: "Создай такой то виджет", но опять будет виснуть интерфейс...

Отдельные потоки нужны только при загрузке в таблицы, а дальше они не понадобятся, значит надо думать как "облегчить" инициализацию и отрисовку этих виджетов, может какие нибудь действия, не связанные с gui вынести в потоки...
Буду думать...


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: UNION labs от Сентябрь 06, 2012, 12:56
И все-таки вам нужно смотреть в сторону model/view, а именно на делегаты, и при их помощи все что нужно отрисовывать.
И можете картинку прикрепить, показать что у вас является одной строкой?


Название: Re: Использование QFuture и QtConcurrent внутри класса с вызовом метода этого класса
Отправлено: Bepec от Сентябрь 06, 2012, 13:10
Делегат бот на выход! (где тот, кто обещался его сделать?  ??? )

Model/View решит твои проблемы. По ней уже написаны сотни тем, пара мануалов и пост на хабрахабре.

PS я тебя понимаю, мой тестовый пример без Model/View на 5000 баттонов тормозит, а с Model/View он белый, пушыстый и выглядит как новый! :D