Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [Qt4] Функция в отдельном потоке, Получение возращаемого значения 
V
    Опции темы
Girin
Дата 20.3.2008, 11:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 81
Регистрация: 6.2.2008

Репутация: нет
Всего: нет



Как можно получить значение возвращаемой функцией запущенной в отдельном потоке (использую QThread)  ? 
PM   Вверх
SABROG
Дата 20.3.2008, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Унаследуй QThread, переопредели функции, которые должны возвращаться значение. Пример из ассистанта:

Код

         class MyThread : public QThread
         {
         public:
             void run();
         };

         void MyThread::run()
         {
             QTcpSocket socket;
             // connect QTcpSocket's signals somewhere meaningful
             ...
             socket.connectToHost(hostName, portNumber);
             exec();
         }


Например так:

Код

         class MyThread : public QThread
         {
         public:
             void run();
         int retVal;
         };

         void MyThread::run()
         {
         //тут пишется код, который будет выполняться в отдельном потоке
             exec();
             retVal = 0; //например возвратим ноль
         }


И проверять это значение, когда придет сигнал finished. Может быть можно и как-то эстетичнее, сейчас в голову ничего не приходит.

Это сообщение отредактировал(а) SABROG - 20.3.2008, 11:46


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Lazin
Дата 20.3.2008, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 2
Всего: 154



добавь к классу-потоку - переменную, в которую записывай результат работы...

но прежде чем оттуда читать - жди пока поток отработает

хотя мне такой дизайн не нравиться, я свои программы строю по другому)))

Добавлено через 6 минут и 17 секунд
Код

class myThread : public QThread
{
int res_;
HANDLE evt_;
public:
    void run() {
        //do things
        res_ = ....
        SetEvent(evt_);
    }

    int get_result()
    {
        WaitForSingleObject(evt_, INFINITE);//ждем пока поток отработае
        return res_;
    }
};


в коде использовал win32 api, так как не знаю, что там в Qt за синхронизация)))
еще не написал конструктор, потому-что лень...

Добавлено через 8 минут и 42 секунды
дурость конечно смешивать winapi и Qt код))
PM MAIL Skype GTalk   Вверх
SABROG
Дата 20.3.2008, 11:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



А какой смысл замораживать приложение в ожидании результирующего значения, зачем тогда поток нужен, если его цель сделать программу рабочей в момент долгих операций ?


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Lazin
Дата 20.3.2008, 12:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 2
Всего: 154



ну я же написал что:
Цитата(Lazin @  20.3.2008,  11:43 Найти цитируемый пост)
хотя мне такой дизайн не нравиться, я свои программы строю по другому)))

во вторых:
если нужно прочитать и использовать результат, то нужно полюбому дождаться завершения потока... а в твоем коде можно использовать результат до того как он будет вычислен, результат же не обязательно должен использоваться в слоте получающем сигнал finished (ну и .... этот ваш Qt)
PM MAIL Skype GTalk   Вверх
SABROG
Дата 20.3.2008, 12:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Если есть условие, что что-то должно сделаться в зависимости от результата в потоке, то почему просто не заставить поток это сделать ? Например во всех моих программах, где я использовал чистый WinApi с потоками основная идея сводилась к тому, чтобы по результату потока поменять что-то в интерфейсе программы - переименовать кнопку, включи/отключить кнопки, вывести текст в edit и т.д. Все это я делал из потока, а не из главного цикла.

Если поток должен вернуть массив данных, то почему просто не передать в него указатель на этот массив, он сам его заполнит. Если без результата из потока невозможно дальнейшее выполнение программы, то обычно создают модальное окно с каким-нибудь progressBarом и кнопкой Cancel. В этом случае само наличие потока нужно только для обеспечения комфортности пользователя, мало ли подумает программа зависла, а так видит окошко перерисовывается, кнопочку можно нажать в любой момент, тормозов как с processAllEvents нету.

Это сообщение отредактировал(а) SABROG - 20.3.2008, 12:53


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Girin
Дата 20.3.2008, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 81
Регистрация: 6.2.2008

Репутация: нет
Всего: нет



Цитата(SABROG @ 20.3.2008,  11:35)
Унаследуй QThread, переопредели функции, которые должны возвращаться значение. Пример из ассистанта:
.........
И проверять это значение, когда придет сигнал finished. Может быть можно и как-то эстетичнее, сейчас в голову ничего не приходит.

Сделал как вы посоветовали , а именно создал класс производный от QThread , переопределил его метод
Код
void DllThread::run()
{
    ///-------Сбор информации  о версии dll ------
    int ApplicationVersion[4] = {0,0,0,0}; // массив с информацией о версии
    const wchar_t * temp=fileName.toStdWString().c_str();
    if(!getFileVersionInfo(temp,ApplicationVersion))//функция на WinAPI
    {
        QMessageBox::information(NULL,"Result","false") ;
        emit finished();
    }
    char str[32];
    sprintf(str,"version %d.%d.%d.%d",ApplicationVersion[0],ApplicationVersion[1],ApplicationVersion[2],ApplicationVersion[3]);
    fileVersion=QString::fromLocal8Bit(str);//поле, которое используется вместо возвращаемого значения
    exec();
}

Далее объявил одно из приватных полей основного класса как поле типа DllThread, и в конструкторе вызвал соостствующий connect. Но сигнал finished() почему то не генерируется и результата вычислений нет ..   Плюс к этому пришлось перенести определение всех методов основного класса(виджет), которые нужно выполнить  в отдельном потоке в класс, унаследованный от QThread. В итоге код стал малочитаемым и запутанным . Есть ли другой подход

Это сообщение отредактировал(а) Girin - 20.3.2008, 14:29
PM   Вверх
SABROG
Дата 20.3.2008, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Есть. Определения никуда не переносить, а прописать френда в класс основного окна. Или передать в конструктор тупо указатель, главное, чтобы окно не деструктнулось перед тем как поток завершится.

Самому отправлять finished() не нужно. Оно приходит, когда поток завершается, само.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Girin
Дата 20.3.2008, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 81
Регистрация: 6.2.2008

Репутация: нет
Всего: нет



Попробовал вариант с передачей указателя в конструктор, получилось как надо. SABROGLazin благодарю за помощь
PM   Вверх
SABROG
Дата 20.3.2008, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Кстати глянь еще QtConcurrent, там какая-то крутая технология распараллеливания потоков по ядрам процессора используется.  smile Помимо этого можно тупо передать функцию которая должна выполняться в потоке, без наследования QThread.

Код

QFutureWatcher *watcher  = new QFutureWatcher();
QObject::connect(watcher, SIGNAL(resultReady(const QVariant&)), myObject, SLOT(handleResult(const QVariant &)));

QString foo();
QFuture<QString> f = QtConcurrent::run(foo);
watcher->setFuture(f);


Это сообщение отредактировал(а) SABROG - 20.3.2008, 15:40


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Girin
Дата 22.3.2008, 01:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 81
Регистрация: 6.2.2008

Репутация: нет
Всего: нет



Да судя по описанию на офф сайте многообещающая технология , но как я понял только в бета разработке и включена в Qt , начиная с версии 4.4 
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.1252 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.