Russian Qt Forum

Qt => Вопросы новичков => Тема начата: rudireg от Ноябрь 04, 2016, 16:52



Название: Приостановка потока
Отправлено: rudireg от Ноябрь 04, 2016, 16:52
Привет. Есть поток, обрабатывающий список неких ресурсов.
Если ресурсов нет, поток должен стоять, как только он видит что появились ресурсы - поток должен начать их обработку (по кругу их постоянно обрабатывает, покуда ресурсы существуют.)

Сделал таким образом, но меня смущает sleep() -  читал что в рабочих программах применение sleep()  не очень хорошо.
Предложите альтернативу.
Код
C++ (Qt)
void Master::processAccounts()
{
   while(true){
       QApplication::processEvents();
 
       //If have not resources, then sleep
       if( !this->accountController->size() ){
           QThread::sleep(1);
           continue;
       }
 
       // Have the resources
       // Process resources ...
   };
}
 


Название: Re: Приостановка потока
Отправлено: kuzulis от Ноябрь 04, 2016, 17:18
Использовать QWaitCondition ?


Название: Re: Приостановка потока
Отправлено: Igors от Ноябрь 04, 2016, 17:20
timerEvent, это событие имеет неск хитростей. Оно генерируется только когда нет др событий, т.е. нет опасности что Вы будете завалены кучей timerEvent. И рекурсия автоматически рубится - когда выскочили в processEvents из timerEvent - там еще раз его не получите

Использовать QWaitCondition ?
"Ой напрасно тетя Вы таблетки пьете"  :)


Название: Re: Приостановка потока
Отправлено: rudireg от Ноябрь 04, 2016, 17:38
 В начале темы видимо я не правильно сформулировал вопрос. Нужно было не поток останавливать,  а выполнение слота.
Сделал так.

Код
C++ (Qt)
void Master::processAccounts()
{
   QEventLoop loop;
   while(true){
       QApplication::processEvents();
       if( !this->accountController->size()){
           QTimer::singleShot(1000, &loop, SLOT(quit()));
           loop.exec();
           continue;
       }
 
      // Do Pocess ...
   };
}
 


Название: Re: Приостановка потока
Отправлено: Old от Ноябрь 04, 2016, 18:13
В начале темы видимо я не правильно сформулировал вопрос. Нужно было не поток останавливать,  а выполнение слота.
А для чего такое делать? Расскажите, что вы хотите получить, возможно есть более правильный путь. :)

Проверка с засыпанием не эффективна. Например, вы проверили что работы нет и заснули на 1 секунду. Через 10 мс после проверки, работа появляется, но поток не будет ее работать, он будет ждать еще 990 мс. А мог бы работать.

kuzulis правильно посоветовал (да и я вам это уже советовал) использовать для этого QWaitCondition. Он для этого и предназначен: если работы нет, поток засыпает на wait, как только работа появилась, поток будят wake.


Название: Re: Приостановка потока
Отправлено: Bepec от Ноябрь 04, 2016, 20:41
Пссс... Если в его пример внедрить ещё 1 сигнал, который будет цепляться к лупу, который будет подаваться при добавлении задачи, его вариант будет удовлетворять всем требованиям :)


Название: Re: Приостановка потока
Отправлено: rudireg от Ноябрь 04, 2016, 21:28
В начале темы видимо я не правильно сформулировал вопрос. Нужно было не поток останавливать,  а выполнение слота.
А для чего такое делать? Расскажите, что вы хотите получить, возможно есть более правильный путь. :)

Проверка с засыпанием не эффективна. Например, вы проверили что работы нет и заснули на 1 секунду. Через 10 мс после проверки, работа появляется, но поток не будет ее работать, он будет ждать еще 990 мс. А мог бы работать.

kuzulis правильно посоветовал (да и я вам это уже советовал) использовать для этого QWaitCondition. Он для этого и предназначен: если работы нет, поток засыпает на wait, как только работа появилась, поток будят wake.

Задача простая...
Программа работает со списком аккаунтов  и выполняет назначенные для них задания.
Есть объект MASTER унаследованный от QOBJECT , который перенесен в новый поток с помощью movetothread
Следовательно MASTER теперь работает на сигналах и слотах (плюс событиях).
Объект MASTER постоянно по кругу мониторит QList  аккаунтов и смотрит есть ли какие либо задания у аккаунтов.
Если задание есть, то для выполнения каждого, объект MASTER с помошью QThreadPool выполняет задания в объекте что унаследован от QRunnable

Вот я и задался вопросом, что если при старте проги, нет аккаунтов в работе, MASTER  их должен ждать, а через время аккаунты появились, тогда MASTER должен их обрабатывать.
Объект MASTER  имеет много слотов, которые могут выполнятся асинхронно... и я подумал, если использовать QWaitCondition - то он заблокирует весь поток... тогда ВСЕ СЛОТЫ объекта MASTER будут остановлены покуда не будет вызван QWaitCondition.wakeAll
А мне нужно что бы ждал только слот, что мониторит список аккаунтов....
QEventLoop  (даже с паузой 1 сек) - это выигрыш с малой кровью на мой взгляд, ибо повявление и исчезновение новых аккаунтов делается 1 или 2 раза на протяжении всей работы программы.



Название: Re: Приостановка потока
Отправлено: Old от Ноябрь 05, 2016, 08:40
Объект не может жить в потоке, объект это набор данных. В отдельном потоке может выполняться какой-то код. Контекст потока в Qt введен исключительно для правильной работы сигналов-слотов между потоками.
Например, у одного объекта MASTER его методы легко могут выполняться в разных потоках.
Если метод processAccounts приходится тормозить, значит его кто-то постоянно вызывает, так может не стоит его вызывать, если для него нет работы?


Название: Re: Приостановка потока
Отправлено: rudireg от Ноябрь 05, 2016, 09:31
Объект не может жить в потоке, объект это набор данных. В отдельном потоке может выполняться какой-то код. Контекст потока в Qt введен исключительно для правильной работы сигналов-слотов между потоками.
Например, у одного объекта MASTER его методы легко могут выполняться в разных потоках.
Если метод processAccounts приходится тормозить, значит его кто-то постоянно вызывает, так может не стоит его вызывать, если для него нет работы?
Вы писали: Например, у одного объекта MASTER его методы легко могут выполняться в разных потоках.
Каким образом? Вы имеете ввиду использование QConcurrent и QThreadPool ?
Если взять допустим QThreadPool , то следует MASTER унаследовать от QRunnable  и вызывать QThreadPool::start(MASTER );
Верно я понял?
Не вижу другого способа выполнять методы MASTER  в иных потоках.
Хотя если тока на сигналах и слотах еще можно реализовать... один сигнал объекта MASTER  соединен с разными СЛОАТМИ других объектов, выполнение которых происходит в разных потоках.


Название: Re: Приостановка потока
Отправлено: Old от Ноябрь 05, 2016, 11:50
Каким образом? Вы имеете ввиду использование QConcurrent и QThreadPool ?
Не имеет значение что использовать, и QtConcurrent и QThreadPool базируются на системных потоках. Если вы запустите два потока, из первого вызовете один метод, а из другого другой, вот вам и работа в разных потоках. :)


Название: Re: Приостановка потока
Отправлено: Igors от Ноябрь 05, 2016, 12:38
Почему не организовать обработку account банальным слот/сигналом? При обновлении accountController испускается сигнал который (через EventLoop нитки) приходит на слот Master::processAccounts, который делает DoProcess и просто завершается. Какая необходимость в организации вторичного цикла?