Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: crashtua от Август 24, 2012, 14:52



Название: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: crashtua от Август 24, 2012, 14:52
Есть такое дело, гуишный поток запускает дочерний, в методе run которого запущен while(true)... Умрут ли в таком случае сигналы и слоты в воркере? Нужно ли принудительно в том цикле обрабатывать евенты?


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: Пантер от Август 24, 2012, 14:54
Кто такой воркер?


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: Serr500 от Август 24, 2012, 15:05
Умрут ли в таком случае сигналы и слоты в воркере? Нужно ли принудительно в том цикле обрабатывать евенты?
Да. Да.


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: Igors от Август 24, 2012, 15:07
Ну не умрут но к ним нельзя будет достучаться т.к. EventLoop не крутится - то ли Вы его вообще не запустили (нет exec) то ли перебили while (true)


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: crashtua от Август 24, 2012, 15:35
Пантер, воркер это Qthread с бесконечным лупом в run.
EventLoop не крутится - то ли Вы его вообще не запустили (нет exec)
Именно, в run нет exec. Если будет exec то тогда не будет моего while(true), который так же необходим, как и EventLoop... А если в ране сделать что то типа
Код
C++ (Qt)
QEventLoop eventLoop;
while(true){
   eventLoop.processEvents();
   //ультранужная задача
}
 
то слоты начнут работать?


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: Bepec от Август 24, 2012, 15:41
Помойму кто-то чегой то не понимает. Вроде бы при запуске потока c переопределённым run, EventLoop создаётся. Слоты работать должны.

PS или у меня опять провалы в памяти и пара моих проектов работают чудом?


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: crashtua от Август 24, 2012, 15:46
Верес, неа, вот обычный run() из QThread
Код
C++ (Qt)
void QThread::run()
{
   (void) exec();
}
 
А вот и exec()
Код
C++ (Qt)
int QThread::exec()
{
   Q_D(QThread);
   QMutexLocker locker(&d->mutex);
   d->data->quitNow = false;
   if (d->exited) {
       d->exited = false;
       return d->returnCode;
   }
   locker.unlock();
 
   QEventLoop eventLoop;
   int returnCode = eventLoop.exec();
 
   locker.relock();
   d->exited = false;
   d->returnCode = -1;
   return returnCode;
}
 
Тут четко видно, что QEventLoop создается в exec(), так что, как подсказывает логика, свой QEventLoop тоже должен проканать...


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: Serr500 от Август 24, 2012, 15:49
Помойму кто-то чегой то не понимает. Вроде бы при запуске потока c переопределённым run, EventLoop создаётся. Слоты работать должны.
start() запускает run(), а Event Loop создаётся в exec(). Если до него в run() цикл, то Event Loop'а нет и, соответственно, сигналы не обрабатываются.

А если в ране сделать что то типа
Код
C++ (Qt)
QEventLoop eventLoop;
while(true){
   eventLoop.processEvents();
   //ультранужная задача
}
 
то слоты начнут работать?
Да.


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: Igors от Август 24, 2012, 15:54
Именно, в run нет exec. Если будет exec то тогда не будет моего while(true), который так же необходим, как и EventLoop... А если в ране сделать что то типа
Код
C++ (Qt)
QEventLoop eventLoop;
while(true){
   eventLoop.processEvents();
   //ультранужная задача
}
 
то слоты начнут работать?
Не так, просто QAplication::processEvents, он static. Обычно нет смысла смешивать 2 техники (сигналы и свой while)


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: crashtua от Август 24, 2012, 16:02
Не так, просто QAplication::processEvents, он static. Обычно нет смысла смешивать 2 техники (сигналы и свой while)
Дело в том, что в том цикле выполняются операции с сокетами в программе, которая совсем не написана на Qt, и мне просто нужно прикрутить к ней GUI. Если я буду запускать QAplication::processEvents() в том цикле, то всякие разные отрисовки, перерисовки, движения мышки могут достаточно ощутимо затормозить работу с сокетами, собственно, сигналы\слоты нужны только для нескольких функций(запустить обработку, остановить, узнать состояние). Потому то мне кажется, что мой вариант будет обрабатывать только то мизерное количество евентов, которое будет припадать на мой воркер, а не все евенты приложения. Если не прав, то поправляйте:).


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: Bepec от Август 24, 2012, 16:47
Вот ненадо мне тут трындить. (это я к тем, которые трындят, что слоты умрут)

Код:
	void run()
{
while (true)
{
Sleep(10);
}
};

Сигнал слоты работают. Так что всё у ТСса работать будет со слотами.

PS помоему такая холиварная тема уже поднималась. И там докопались вроде(давно было ), что start() вызывает exec, если переопределён run().




Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: andrew.k от Август 24, 2012, 16:51
Пантер, воркер это Qthread с бесконечным лупом в run.
EventLoop не крутится - то ли Вы его вообще не запустили (нет exec)
Именно, в run нет exec. Если будет exec то тогда не будет моего while(true), который так же необходим, как и EventLoop... А если в ране сделать что то типа
Код
C++ (Qt)
QEventLoop eventLoop;
while(true){
   eventLoop.processEvents();
   //ультранужная задача
}
 
то слоты начнут работать?
работать-то начнут, но так же и сожрется проц.


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: andrew.k от Август 24, 2012, 17:17
Код:
	void run()
{
while (true)
{
Sleep(10);
}
};

Сигнал слоты работают. Так что всё у ТСса работать будет со слотами.
Смотря какие. В гуи будут работать, а в потоке нет.
Чего холиварного в этой теме?

Вот ненадо мне тут трындить. (это я к тем, которые трындят, что слоты умрут)
...
Сигнал слоты работают. Так что всё у ТСса работать будет со слотами.
А вот и докатились:
Bepec
 Джедай : наставник для всех
 ;D ;D ;D


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: Bepec от Август 24, 2012, 17:31
Код:
class SBFiber : public QThread
{
Q_OBJECT

public:
SBFiber(QObject *parent = 0);
~SBFiber();
void run()
{
connect(this, SIGNAL(sig()), SLOT(slot()));
while (true)
{
emit sig();
Sleep(10);

}
};
public slots:
void slot()
{
qDebug() << "fdsfdf";
};
signals:
void sig();
private:

};

andrew.k сам попробуй. Работают и внешние и внутренние слоты, НЕЗАВИСИМО откуда посылаются/принимаются сигналы.

Я бы себе взял другой титул, но система для всех одна.

PS я в отличие от тебя пробую/получаю результат/отвечаю ;) А не бросаюсь словами.


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: andrew.k от Август 24, 2012, 17:33
PS я в отличие от тебя пробую/получаю результат/отвечаю ;) А не бросаюсь словами.
не смеши меня!


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: Bepec от Август 24, 2012, 17:34
Твоя реплика только доказывает мою правоту  ;D


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: andrew.k от Август 24, 2012, 17:44
PS я в отличие от тебя пробую/получаю результат/отвечаю ;) А не бросаюсь словами.
Тут и пробовать ничего. Эта "холиварная" тема не стоит и выеденного яйца.
В отличие от тебя я понимаю, что пишу.
В твоем примере слот к сигналу коннектится в режиме AutoConnection.
А т.к. сигнал и слот в одном потоке, то они связываются через DirectConnection.
Таким образов emit sig() в твоем примере просто прямой вызов слота (если тебе это о чем-то говорит).
Для танкиста: этот сигнал не проходит через очередь. Для совсем танкиста можешь заменить emit sig(); на slot(); ничего не изменится!

А вот если сигнал будет отправлен из другого потока, например, из ГУИ, то он никогда в жизни не дойдет до твоего слота в такой реализации!
Либо добавь пятый параметр Qt::QueuedConnection. И сиди осознавай.

Конечно же очевидно, что ты все это понимаешь, и именно это и имел ввиду, а я просто погорячился.  >:(
А по правде, ты очень достал своими бессмысленными и беспощадными изречениями.


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: andrew.k от Август 24, 2012, 17:50
Твоя реплика только доказывает мою правоту  ;D
Мне в очередной раз стыдно за тебя, Джедай Верес.


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: Bepec от Август 24, 2012, 17:51
Кхм. andrew.k включи логику. Зачем я приводил по твоему в первый раз кусок кода без сигнала? Затем, что сигнал, который вызывает приведённый слот подключен к кнопке на главной форме. И при нажатии кнопки (О чудо) происходит вызов слота :D

Да, согласен, чуть неясно получилось - слот недокопировал.

PS ПОПРОБУЙ а потом говори, благодетель самаритянский :D



Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: Igors от Август 24, 2012, 17:58
Если я буду запускать QAplication::processEvents() в том цикле, то всякие разные отрисовки, перерисовки, движения мышки могут достаточно ощутимо затормозить
Он возьмет EventLoop той нитки из которой вызван, соответственно только посланные ей события (сигналы) будут извлекаться. Надо только сделать exec(). Ваш вариант вполне возможен, просто ничего не выигрывает по сравнению с обычным


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: andrew.k от Август 24, 2012, 18:06
Если я буду запускать QAplication::processEvents() в том цикле, то всякие разные отрисовки, перерисовки, движения мышки могут достаточно ощутимо затормозить
Он возьмет EventLoop той нитки из которой вызван, соответственно только посланные ей события (сигналы) будут извлекаться. Надо только сделать exec(). Ваш вариант вполне возможен, просто ничего не выигрывает по сравнению с обычным
постоянный вызов processEvents() будет зря жрать процессороное время.


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: Bepec от Август 24, 2012, 18:11
Извиняюсь, был неправ :D

Всего то забыл moveToThread сделать :D

По теме: а что мешает запустить еxec, и потом зациклить вызов функции whileBlaBlaBla() с помощью допустим таймера?

Вроде же получится обычный цикл в потоке и поток будет принимать внешние сигналы, ннэ?


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: crashtua от Август 24, 2012, 18:15
Возможно, я не до конца описал проблему, все слоты должны запускаться в потоке-воркере. Теперь, несколько замечаний к Верес:
И там докопались вроде(давно было ), что start() вызывает exec, если переопределён run().
Какими же средствами с++ можно узнать, переопределялся ли метод?(конечно, можно сделать типа bool isRedefined = true,и стандартной реализации выставить в фолс, но Qt писался грамотными людьми, и такого быдлокода там нету:))
Код:
	void run()
{
while (true)
{
Sleep(10);
}
};
Опять же, наверно потому что я не уточнил, что слоты должны выполнятся в воркере... Что бы такое условие выполнилось, мы должны объект с нашим слотом переместить в воркер(в моем случае это он сам). Переместим: worker.moveToThread(&worker);. Запускаем, а слоты не работают, о ужас :(. А вот так
Код
C++ (Qt)
   while(true){
       sleep(0.01);
       loop.processEvents();
   }
 
слоты работают. Если надо, могу скинуть пример, который полностью обрисовывает ситуацию.
там правда немного быдлокода, связано с тем, что потоки не успевают запуститься к тому моменту как я пробую емитить сигнал


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: crashtua от Август 24, 2012, 18:17
Извиняюсь, был неправ :D
Всего то забыл moveToThread сделать :D
Пока писал ответ, и проверал на примере, Вы сами муванули его :)


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: andrew.k от Август 24, 2012, 18:18
Извиняюсь, был неправ :D

Всего то забыл moveToThread сделать :D
Не в этом дело, а в том, что ты свой пример даже не запускал.

По теме: а что мешает запустить еxec, и потом зациклить вызов функции whileBlaBlaBla() с помощью допустим таймера?

Вроде же получится обычный цикл в потоке и поток будет принимать внешние сигналы, ннэ?
Редкий случай, когда Верес говорит, что-то дельное, поэтому переведу на человечий.
Нужно то, что ты делаешь внутри своего while(true) разбить на подзадачи и выполнять каждый шаг по сигналу.
Получил сигнал (от таймера или от того, кто тебе данные на обработку дает - обработал, дальше ждешь, получил - обработал).
Но это если эти сигналы действительно нужны.


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: Bepec от Август 24, 2012, 18:21
Мой пример потому и запускался, что работал в 1 потоке ;)


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: crashtua от Август 24, 2012, 18:30
Редкий случай, когда Верес говорит, что-то дельное, поэтому переведу на человечий.
Нужно то, что ты делаешь внутри своего while(true) разбить на подзадачи и выполнять каждый шаг по сигналу.
Получил сигнал (от таймера или от того, кто тебе данные на обработку дает - обработал, дальше ждешь, получил - обработал).
Но это если эти сигналы действительно нужны.
Та там столько действий в том цикле, что мне страшно даже трогать, не хочу поломать (программа не моя). А на то что processEvents() будет жрать процессорное время ээээ... Хотел заикнутся что не будет, потому что в exec() QEventLoop'а тоже в цикле вызывается processEvents(), но увидел в исходниках, что processEvents() в  QEventLoop'е при отсутствии евентов их ожидает... А вариант с таймером почти подходит, но там сокеты... Хотелось бы моментального отклика, а не по таймеру...


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: Bepec от Август 24, 2012, 18:33
Эмм... Таймер ставишь в 0 - получаешь такой же while(true) с работающими слотами :)


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: andrew.k от Август 24, 2012, 18:37
Мой пример потому и запускался, что работал в 1 потоке ;)
Ты свой пример даже не запуска ни разу, скопировал у какого-то дурака и размножаешь.
Во вложении пример, который я написал.
Вот и расскажи мне как же так в твоем примере сигналы успешно работают, а в моем нет?
Что я делаю не так?


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: andrew.k от Август 24, 2012, 18:40
Редкий случай, когда Верес говорит, что-то дельное, поэтому переведу на человечий.
Нужно то, что ты делаешь внутри своего while(true) разбить на подзадачи и выполнять каждый шаг по сигналу.
Получил сигнал (от таймера или от того, кто тебе данные на обработку дает - обработал, дальше ждешь, получил - обработал).
Но это если эти сигналы действительно нужны.
Та там столько действий в том цикле, что мне страшно даже трогать, не хочу поломать (программа не моя). А на то что processEvents() будет жрать процессорное время ээээ... Хотел заикнутся что не будет, потому что в exec() QEventLoop'а тоже в цикле вызывается processEvents(), но увидел в исходниках, что processEvents() в  QEventLoop'е при отсутствии евентов их ожидает...
Молодец. Жаль что не все так делают, а сначала понапишут непонятно чего, а потом думают, да примерчики запускают)


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: crashtua от Август 24, 2012, 18:44
Хм, посмотрел исходники той проги, там цикл вот такой:
Код
C++ (Qt)
while( 1 )
{
// block for 50ms on all sockets - if you intend to perform any timed actions more frequently you should change this
// that said it's likely we'll loop more often than this due to there being data waiting on one of the sockets but there aren't any guarantees
 
if( gGHost->Update( 50000 ) )
break;
}
 
50000 - таймаут для функции http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx). + до того таймаута там выполняется еще куча всяких непонятных радостей... Теперь вопрос: можно ли сделать таймер так, что бы он не посылал новый сигнал до того, как завершится старый, и при этом что бы не блокировался GUI поток(мне бы стоило почитать доки про таймер, но как то жутко лень, и так сегодня начитался и доков, и сорцов...)?


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: andrew.k от Август 24, 2012, 18:45
А вариант с таймером почти подходит, но там сокеты... Хотелось бы моментального отклика, а не по таймеру...
Я думаю, что лучше тебе сделать так.
Пишешь некоторый класс (ProblemSolver), вообще не думая о потоках, который делает всю эту работу, которая у тебя запихана в твой цикл.
Это будет проще и кошернее.
Затем создаешь два объекта QThread (оригинальный без всякого наследования) и свой класс ProblemSolver.
и делаешь ему moveToThread.
Код
C++ (Qt)
solver = new ProblemSolver();
thread = new QThread(this);
solver->moveToThread(thread);
thread->start();
solver->startSolving();
как-то так. И будет оно работать как надо.


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: andrew.k от Август 24, 2012, 18:48
Хм, посмотрел исходники той проги, там цикл вот такой:
Код
C++ (Qt)
while( 1 )
{
// block for 50ms on all sockets - if you intend to perform any timed actions more frequently you should change this
// that said it's likely we'll loop more often than this due to there being data waiting on one of the sockets but there aren't any guarantees
 
if( gGHost->Update( 50000 ) )
break;
}
 
50000 - таймаут для функции http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx). + до того таймаута там выполняется еще куча всяких непонятных радостей... Теперь вопрос: можно ли сделать таймер так, что бы он не посылал новый сигнал до того, как завершится старый, и при этом что бы не блокировался GUI поток(мне бы стоило почитать доки про таймер, но как то жутко лень, и так сегодня начитался и доков, и сорцов...)?
Ты можешь просто игнорировать сигнал от таймера, если он тебе не нужен.


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: crashtua от Август 24, 2012, 19:06
А вариант с таймером почти подходит, но там сокеты... Хотелось бы моментального отклика, а не по таймеру...
Я думаю, что лучше тебе сделать так.
Пишешь некоторый класс (ProblemSolver), вообще не думая о потоках, который делает всю эту работу, которая у тебя запихана в твой цикл.
Это будет проще и кошернее.
Затем создаешь два объекта QThread (оригинальный без всякого наследования) и свой класс ProblemSolver.
и делаешь ему moveToThread.
Код
C++ (Qt)
solver = new ProblemSolver();
thread = new QThread(this);
solver->moveToThread(thread);
thread->start();
solver->startSolving();
как-то так. И будет оно работать как надо.
А как же оно будет работать, если мы муванем ProblemSolver и вызовем там цикл, наш thread повиснет же...


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: andrew.k от Август 24, 2012, 19:08
А вариант с таймером почти подходит, но там сокеты... Хотелось бы моментального отклика, а не по таймеру...
Я думаю, что лучше тебе сделать так.
Пишешь некоторый класс (ProblemSolver), вообще не думая о потоках, который делает всю эту работу, которая у тебя запихана в твой цикл.
Это будет проще и кошернее.
Затем создаешь два объекта QThread (оригинальный без всякого наследования) и свой класс ProblemSolver.
и делаешь ему moveToThread.
Код
C++ (Qt)
solver = new ProblemSolver();
thread = new QThread(this);
solver->moveToThread(thread);
thread->start();
solver->startSolving();
как-то так. И будет оно работать как надо.
А как же оно будет работать, если мы муванем ProblemSolver и вызовем там цикл, наш thread повиснет же...
Что значит повиснет? Зависание это неконтролируемый бесконечный цикл, а если он контролируемый, то это не зависание, а "длительные вычисления" :)
Он просто будет кушать процессор и твоя забота, чтобы он его кушал не в холостую)
По завершению из цикла нужно выйти и можно остановить поток, а можно и не останавливать.


Название: Re: GUI поток и воркер, в котором запущен while(true)-умрут ли слоты?
Отправлено: crashtua от Август 24, 2012, 20:26
Принял решение остановится на следующем варианте: класс Worker имеет слот, в котором содержится тело цикла while(true), в этом же классе(Worker) создается таймер с интервалом 50 мс. Создается поток, в него мувается мой Worker. Работает, тело цикла запускается с нужной периодичностью, слоты запускаются с созданого потока, GUI и Worker не оказывают негативного влияния один на другого. Всем спасибо за внимание, очень помогли.