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

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

Страниц: [1] 2 3 ... 5   Вниз
  Печать  
Автор Тема: Многопоточное программирование  (Прочитано 54401 раз)
lex_pc
Гость
« : Октябрь 31, 2013, 01:06 »

Доброго времени суток господа!
Вот решил давеча повысить свои знания в Qt области, в частности в области многопоточности,
С многопоточностью я и на C# не особо дружу, так только создал поток, закинул в него указатель на функцию и был таков.

А вот в Qt беда.

Шлее пишет, что для использования потоков необходимо наследоваться от QThread, и переопределять метод run().
Отлично, а если у меня несколько функций, которые я хочу выполнять в потоке, что создавать для каждой наследника?
Пробовал в run() сделать вот так:

Код:
void myThread::run()
{
    emit num();
}

И связывать сигнал каждого созданного мною потока с определённой функцией класса MainWindow, однако в таком случае
происходит поочерёдное выполнение методов ( оно то и понятно в теле run() только сигнал, а сама-то функция в другом классе).

В C# вот можно так:

Код:
Thread threadNumA(new ParameterizedThreadStart(numA);    // void numA()
Thread threadNumB(new ParameterizedThreadStart(numB);    // void numB()

threadNumA.Start();
threadNumB.Start();
//Ждём пока они не finished
threadNumA.Join();
threadNumB.Join();


А вот в Qt так сделать нельзя ( пробовал создавать указатель на функцию MainWindow  и передавать).
Можно также использовать QConcurent и его почти аналог QRunnable, однако хотелось бы сделать без них.
так, а теперь собственно вопрос:
Можно ли каким-либо образом передавать указатель на функцию в run() и там выполнять (как в C#) или же
для каждого метода при использовании QThread необходимо создавать потомок со своей перегруженной функцией run() ?
Записан
carrygun
Гость
« Ответ #1 : Октябрь 31, 2013, 05:28 »

На форуме есть много тем про это, да и в самой справке с примерами все рассказано.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Можно ли каким-либо образом передавать указатель на функцию в run() и там выполнять (как в C#) или же
для каждого метода при использовании QThread необходимо создавать потомок со своей перегруженной функцией run() ?
А чего ж нельзя?
Код
C++ (Qt)
#include <QThread>
 
typedef void (*RunProc)( void );
 
class MyThread : public QThread {
public:
MyThread( RunProc proc ) : mProc(proc) {}
 
void run( void )
{
mProc();
}
 
RunProc mProc;
};
 
void MyRun1( void )
{
// do something
}
 
void MyRun2( void )
{
// do something
}
 
int main()
{
MyThread thread1(MyRun1);
MyThread thread2(MyRun2);
thread1.start();
thread2.start();
 
thread1.wait();
thread2.wait();
 
   return 0;
}
 
Записан
AlFoX
Гость
« Ответ #3 : Октябрь 31, 2013, 11:33 »

Чего-то непонятно, ты говоришь что в Qt "так сделать нельзя" и в то же время хочешь хочешь городить костыли без QtConcurrent?
QtConcurrent::run - аналог твоего кода на С#.

К тому же наследование от QThread уже давно обявлено неоптимальным и не рекоммендуется.
Вместо этого используй QObject::moveToThread()
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #4 : Октябрь 31, 2013, 11:34 »

std::thread? http://ru.cppreference.com/w/cpp/thread/thread

Код
C++ (Qt)
void thead_func() { /* ... */}
 
int main()
{
   std::thread thread(thread_func);
   thread.join();
 
   return 0;
}
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
lex_pc
Гость
« Ответ #5 : Октябрь 31, 2013, 18:00 »

Igors,
спасибо огромное.

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

m_ax,
std::  ? Так мы же вроде на Qt


А теперь, собственно,  это же вопрос более углубленно:

Код:
#include <QThread>
 
typedef void (*RunProc)( void );
 
class MyThread : public QThread {
public:
MyThread( RunProc proc ) : mProc(proc) {}
 
void run( void )
{
mProc();
}
 
RunProc mProc;
};
 
void MyRun1( void )
{
// do something
}
 
void MyRun2( void )
{
// do something
}
 
int main()
{
MyThread thread1(MyRun1);
MyThread thread2(MyRun2);
thread1.start();
thread2.start();
 
thread1.wait();
thread2.wait();
 
    return 0;
}

сие действо работает, однако если функции, сообщаемые потоку будут из
другого класса, то простым указателем на функцию не обойтись (вроде бы).

А теперь вопрос: каким образом можно связать потомок QThread с классом
(ну допустип Alfavit), у которого, например 2 или 3 метода?
Записан
mutineer
Гость
« Ответ #6 : Октябрь 31, 2013, 18:10 »

Можно обойтись простым указателем на интерфейс, который декларирует необходимый метод. Или два метода. Или три метода
Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #7 : Октябрь 31, 2013, 18:13 »

AIFox,
пусть и костыли, зато несколько "костылей" будут получше чем одна "нога",
к тому же, на мой взгляд, ножка какая-то кривоватая ( скорее всего жестоко
ошибаюсь).
Ошибаетесь, QtConcurrent хорошая вещь.

m_ax,
std::  ? Так мы же вроде на Qt
std - это стандартная библиотек C++, Qt - это одна из библиотек. так почему не воспользоваться стандартной?

А теперь вопрос: каким образом можно связать потомок QThread с классом
(ну допустип Alfavit), у которого, например 2 или 3 метода?
для этого достаточно почитать книгу про C++ или что нибудь в интернете, например: http://alenacpp.blogspot.ru/2007/04/blog-post.html
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Октябрь 31, 2013, 19:04 »

А теперь вопрос: каким образом можно связать потомок QThread с классом
(ну допустип Alfavit), у которого, например 2 или 3 метода?
Лучше сделать интерфейс, напр
Код
C++ (Qt)
struct CCalculator {
virtual void DoCalc( void ) = 0;
};
Подсовываем его MyThread
Код
C++ (Qt)
class MyThread : public QThread {
public:
MyThread( CCalculator * calc ) : mCalc(calc) {}
 
void run( void )
{
mCalc->DoCalc();
}
 
CCalculator * mCalc;
};
 
Это все остается неизменным. А теперь клепаем маленькие классики (можно прямо в инклуде), напр

Код
C++ (Qt)
struct MyCalc1 : public CCalculator {
MyCalc1( Alfavit * a ) : mAlpha(a) {}
void DoCalc( void )
{
  mAlpha->DoSomething();
}
 
Alfavit * mAlpha;
};
 
Использование
Код
C++ (Qt)
MyCalc1 calc1(alphavit);
MyThread thread1(&calc1);
thread1.start();
thread1.wait();
Можно и по-другому, напр
Код
C++ (Qt)
struct Alphavit : public CCalculator {
void DoCalc( void );
};
Так "ызячнее" но требует вмешательства в имеющиеся классы
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Октябрь 31, 2013, 19:15 »

std - это стандартная библиотек C++, Qt - это одна из библиотек. так почему не воспользоваться стандартной?
Qt "пожирнее". Напр как узнать что std::thread завершилась? Ведь join (QThread::wait) хорош лищь для учебного примера
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #10 : Октябрь 31, 2013, 19:45 »

Ведь join (QThread::wait) хорош лищь для учебного примера
ну конечно..  Строит глазки

Цитировать
Qt "пожирнее". Напр как узнать что std::thread завершилась?
В стандартную библиотеку потоков входит также std::future/std::promise
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Октябрь 31, 2013, 20:13 »

В стандартную библиотеку потоков входит также std::future/std::promise
Ну и как мне связать это с std::thread? Открываю http://www.cplusplus.com/reference/thread/thread/ (приличный справочник), никаких намеков на future/promise не вижу. А вот открыв букварь спустя минуты так 2 (максиум) увижу сигнал finished (карета подана). Ну и спрашивается - на хрена  мне грызть "гранит std" если есть куда более легкая и приятная возможность?

ну конечно..  Строит глазки
Детонька, Вы мне глазки не стройте  Улыбающийся Первая либа которую я изучал была Turbo Professional - и это было круто (тогда, в 1990). И я помню свое стремление "объять необъятное" - ну примерно как у Вас. С той поры ничего (в принципе) не меняется. по-прежнему есть ръяно изучающие, но я уже не один из них Улыбающийся
Цитировать
и это пройдет
Записан
lex_pc
Гость
« Ответ #12 : Октябрь 31, 2013, 20:33 »

Спасибо всем огромное господа.
Действительно, надо бы мне быть повнимательнее.
Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #13 : Октябрь 31, 2013, 20:39 »

Ну и как мне связать это с std::thread?
Ну так m_ax все новые возможности показывает лично Страуструп, приезжает к нему домой и рассказывает/показывает. И ко мне он приезжает. И ко многим другим. Вы просто забыли подписаться у него на сайте, что бы он приезжал и вам тоже рассказывал.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Октябрь 31, 2013, 21:06 »

Ну так m_ax все новые возможности показывает лично Страуструп, приезжает к нему домой и рассказывает/показывает. И ко мне он приезжает. И ко многим другим. Вы просто забыли подписаться у него на сайте, что бы он приезжал и вам тоже рассказывал.
Та на здоровье, пусть приезжает Улыбающийся Конечно можно достичь немеряных высот в сынтаксисе (и звдрочить текст до полной неузнаваемости) - но это никак не наполнит карман  Улыбающийся
Цитировать
В конце-концов цель программирования в составлении полезных программ, а не в следовании каким-то правилам
Р. Журден (не ручаюсь за точность цитаты)
Записан
Страниц: [1] 2 3 ... 5   Вверх
  Печать  
 
Перейти в:  


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