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

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

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: waitForDone  (Прочитано 10191 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Июнь 23, 2021, 09:27 »

Добрый день

Создал QThread (рабочую) и подбрасываю ей работу сигналами из главной нитки, все устраивает. Но в какой-то момент главная должна дождаться что у рабочей нет больше задач. Др словами нужен ф-ционал QThreadPool::waitForDone но для конкретной рабочей нитки. Как это сделать технично, не влезая в очереди, примитивы синхронизации и.т.п. ?

Спасибо
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #1 : Июнь 29, 2021, 15:56 »

То есть надо дождаться завершения QThread ? Для этого есть сигнал QThread::finished()
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Июнь 29, 2021, 16:28 »

То есть надо дождаться завершения QThread ? Для этого есть сигнал QThread::finished()
То есть нет, завершать рабочую никто не хотел (QThreadPool мы же не завершаем). WaitForDone должна вернуть упр-е когда рабочая не имеет больше задач и ожидает их (в своем exec)
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #3 : Июнь 30, 2021, 15:44 »

Ну, тогда свой сигнал сделать, и бросать его, если задач нет.
Какая-то призрачная проблема, если честно.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Июнь 30, 2021, 17:13 »

Ну, тогда свой сигнал сделать, и бросать его, если задач нет.
Какая-то призрачная проблема, если честно.
Какой сигнал и как (или куда) его бросать? Кароч, "а можна пример"?  Улыбающийся
Записан
RedDog
Частый гость
***
Offline Offline

Сообщений: 221


Просмотр профиля
« Ответ #5 : Июль 01, 2021, 14:36 »

Код:
void ThreadWrapper::threadFunc()
{
    while (!done)
        doWork();
   emit workFinished();
}
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Июль 02, 2021, 06:06 »

Код:
void ThreadWrapper::threadFunc()
{
    while (!done)
        doWork();
   emit workFinished();
}
Здесь нет ожидания задачи, т.е. этот код годится для параллельного выполнения только одной, потом надо нитку перезапускать. Гораздо удобнее то что предлагает Qt по умоочанию: создать QThread и сделать start. Нитка войдет  в свой событийный цикл (exec). Теперь можно подкармливать ее задачами просто посылая ей сигналы (QueuedConnection). Как не раз жевалось в прошлом, лучше/грамотнее пулять сигналами не самой нитке, а "воркеру".

Вот. Теперь (стартовый пост) надо дождаться  когда рабочая нитка сделает все свои текущие дела - не путать с завершением.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #7 : Июль 02, 2021, 16:09 »

Код:

void WorkerThread::run()
{
    while (!isInterruptionRequested())
   {
      while (hasSomethingToDo())
          doWork();

      Q_EMIT notingToDo();

      while (!hasSomethingToDo() && !isInterruptionRequested())
          sleep(1);      
    }
}


Внешний цикл крутится, пока кто-то не запросит interruption.
Пока есть чего делать, делаем doWork().
Как только работа закончилась, "пуляем" nothingToDo() и зависаем в "пустышке", пока снова работы не подвалит.
Чтоб ресурсы не жрались, делаем sleep/msleep (это важно, а то потог будет ждат около 10% проца впустую).
« Последнее редактирование: Июль 02, 2021, 16:20 от Racheengel » Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Июль 03, 2021, 08:50 »

Как это сделать технично, не влезая в очереди, примитивы синхронизации и.т.п. ?
А предлагая hasSomethingToDo мы признаем что очередь имеем/храним, а это не так уж мало еще кода. Вообще зачем использовать свой run вместо exec по дефаулт?  В чем "выйгрышь"? Испускание notingToDo некорректно, в этот (злополучный) момент главная как раз посылает новую работу, просто рабочая ее еще не увидела. Корявый (m)sleeo тоже "не украшает".

И как из главной дождаться момента "нет работы"? Требуется синхронка, а не отлов сигнала (к тому же неверного).
Записан
RedDog
Частый гость
***
Offline Offline

Сообщений: 221


Просмотр профиля
« Ответ #9 : Июль 03, 2021, 19:06 »

Код:
void ThreadWrapper::threadFunc()
{
    while (!done)
        doWork();
   emit workFinished();
}
Здесь нет ожидания задачи, т.е. этот код годится для параллельного выполнения только одной, потом надо нитку перезапускать. Гораздо удобнее то что предлагает Qt по умоочанию: создать QThread и сделать start. Нитка войдет  в свой событийный цикл (exec). Теперь можно подкармливать ее задачами просто посылая ей сигналы (QueuedConnection). Как не раз жевалось в прошлом, лучше/грамотнее пулять сигналами не самой нитке, а "воркеру".

Вот. Теперь (стартовый пост) надо дождаться  когда рабочая нитка сделает все свои текущие дела - не путать с завершением.
С чего вдруг перезапускать?
ThreadWrapper::moveToThread в конструкторе и будет постоянно крутиться в отдельном своем потоке.
А ThreadWrapper::threadFunc() это либо слот, либо через invokeMethod его дернуть в своем потоке.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Июль 04, 2021, 11:34 »

С чего вдруг перезапускать?
ThreadWrapper::moveToThread в конструкторе и будет постоянно крутиться в отдельном своем потоке. А ThreadWrapper::threadFunc() это либо слот, либо через invokeMethod его дернуть в своем потоке.
Опять-таки, требуется (синхронное) ожидание, а не сигнал. Но главное - такая конструкция не будет работать корректно. Пожуем
Код:
    while (!done)               // while (hasSomethingToDo())
        doWork();
   <-- пробой
   emit workFinished();
Допустим done = true, и рабочая нитка приступает к испусканию workFinished. В этот момент главная пуляет следующую задачу, в итоге главная получит сигнал когда последние задачи возможно еще выполняются в рабочей. Кстати защита мутексом здесь ничего не дает.

И снова - не вижу откуда взять "done" не связываясь с (хлопотливой) очередью.
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #11 : Июль 05, 2021, 09:21 »

Строго говоря, аналогом QThreadPool::waitForDone является QThread::wait.
Здесь же требуется дождаться выполнения всех задач в потоке.

Возможно, так получится подождать. Сам не пробовал).

Код
C++ (Qt)
thread->eventDispatcher()->processEvents( QEventLoop::AllEvents )
 
Записан
RedDog
Частый гость
***
Offline Offline

Сообщений: 221


Просмотр профиля
« Ответ #12 : Июль 05, 2021, 09:28 »

Опять-таки, требуется (синхронное) ожидание, а не сигнал.
std::async

PS: ожидание асинхронной задачи с остановкой потока - проблемы в архитектуре (мое имхо)
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #13 : Июль 05, 2021, 13:49 »

PS: ожидание асинхронной задачи с остановкой потока - проблемы в архитектуре (мое имхо)

Вот у меня тоже закрались подобные подозрения.
Зачем вообще главному потоку знать, что воркеру "делать нечего", в чем суть задачи? Балансирование загрузки? Так нет, судя по всему, воркер только один.
Пусть главный поток сам следит о том, что он на обратку отдал. Воркер почему этим заниматься то должен??
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Июль 05, 2021, 18:06 »

Строго говоря, аналогом QThreadPool::waitForDone является QThread::wait.
Ну никак не "строго", о (затратном) завершении речь не идет. А предложение processEvents - это куча побочных эффектов (лекарство хуже болезни)

std::async
И сразу дустом в рыло Улыбающийся

PS: ожидание асинхронной задачи с остановкой потока - проблемы в архитектуре (мое имхо)
Вот у меня тоже закрались подобные подозрения.
Зачем вообще главному потоку знать, что воркеру "делать нечего", в чем суть задачи? Балансирование загрузки? Так нет, судя по всему, воркер только один.
Пусть главный поток сам следит о том, что он на обратку отдал. Воркер почему этим заниматься то должен??
Ага, стандартное "плохая задача". Заметим что точно такой же ф-ционал QThreadPool::waitForDone почему-то не вызывает никаких вопросов. Типовое использование
Код
C++ (Qt)
// main thread
for (...) {
 ...
 if (..)
  emit SignalDoSomething(options);  // QThreadPool::addTask(options)
 ..
}
 
waitForDone();
Накидал задач и жду пока все сварится. Считать это "плохой архитектурой" нет оснований. Синхронка не есть "плохо", она менее гибка, но есть масса ситуаций когда нельзя связываться с др событиями пока данная  (крытыческая) часть кода не завершена. Поэтому иногда ожидание неизбежно/необходимо. А сколько рабочих ниток (одна или N) - чисто специфика задачи.

Ну и вообще - неужели это такая страшная задача которой надо изо всех сил избегать? Улыбающийся Напр есть простецкое решение:

- завести атомарный счетчик. напр m_taskСount. Главная (посылающий) его инкрементирует, рабочая наоборот, декрементирует. Тогда
Код
C++ (Qt)
void waitForDone( void )
{
 while (m_taskCount)
   QThread::msleep(2);
}
 
Кстати как оформить чище, без sleep? Одно время народ увлекался всякими "футурами", может применить? Или то просто была "дань моде"? Улыбающийся

Потом увидел еще решение. В раннем детстве смотрел фильм "про шпионов", запомнился эпизод
Цитировать
- Вот она прислала письмо, пишет что все норм. Прочитать?

- Не надо, если все норм она должна была прислать чистый лист бумаги
Думается здесь такой приемчик проходит. А может еще есть решения? Думать бум? Или только молиться на великий дуст и.т.п. ? Улыбающийся
Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


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