LINUX.ORG.RU

Qt и распараллеливание задач

 


0

2

Здравствуйте! Я нуб в программировании, немного знаю С, С++ (прочитал пару книжек).

Решил написать простенькую GUI программу на Qt для работы с API удаленного сервера. Задача программы - при наступлении определённых условий отправлять на сервер post запрос. В программе нужно реализовать возможность одновременного выполнения нескольких однотипных задач. Алгоритм такой задачи:
Проверить условие. Если true - отправить post запрос серверу, если false - ждать 2 секунды, перейти к проверке условия.

Решил использовать по отдельному потоку для каждой задачи, чтобы они могли работать параллельно. Собираюсь реализовать это так: При нажатии на кнопку запускается метод, в котором создаётся объект класса QThread, который будет управлять отдельным потоком, в него передаётся объект который будет выполнять работу, поток запускается, работа метода закончена. Но тут у меня возникло несколько вопросов:
1. При повторном нажатии на кнопку метод, к ней присоединённый, создаст второй объект класса QThread, указатель на первый объект будет переопределён, а доступ к первому объекту будет потерян. Можно ли как-то реализовать механизм назначения имени указателя на объект потока в зависимости от номера нажатия на кнопку? Выражения в левой части определения переменной как я понял не допускаются.
2. Таких потоков может быть несколько десятков. Может ли большое количество потоков повлиять на быстродействие программы, если в моменте большая часть потоков станет отправлять запрос на сервер? Есть другие способы реализации моей задачи?

Проверить условие.

Если проверка условия не занимает много времени, то второй поток не нужен. QTimer на 2 секунды будет достаточно.

При повторном нажатии на кнопку метод, к ней присоединённый, создаст второй объект класса QThread, указатель на первый объект будет переопределён, а доступ к первому объекту будет потерян.

Создавай поток один раз при запуске программы. Соедини сигнал кнопки со слотом твоего объекта, который находится в созданном потоке (moveToThread).

Таких потоков может быть несколько десятков. Может ли большое количество потоков повлиять на быстродействие программы, если в моменте большая часть потоков станет отправлять запрос на сервер?

Зависит от количества потоков и их нагрузки. Ты там гигабайты по сети гоняешь или нет?

Есть другие способы реализации моей задачи?

Один поток, который берёт задания из очереди и выполняет.

ox55ff ★★ ()
Ответ на: комментарий от ox55ff

Ты там гигабайты по сети гоняешь или нет?

Нет, файлы не отсылаю. Запросы с авторизацией и передачей команды на выставление ордера. Сервер - криптобиржа.

Один поток, который берёт задания из очереди и выполняет.

Где почитать про очередь?

g3nt00user ()
Ответ на: комментарий от g3nt00user

Запросы с авторизацией и передачей команды на выставление ордера.

Выглядит просто. Я бы в начале попробовал без второго потока. QNetworkAccessManager асинхронный, так что он без проблем уживётся в одном потоке с таймером.

Где почитать про очередь?

Гугли про шаблон producer/consumer.

ox55ff ★★ ()
Ответ на: комментарий от ox55ff

Я бы в начале попробовал без второго потока. QNetworkAccessManager асинхронный, так что он без проблем уживётся в одном потоке с таймером.

Спасибо за совет. Действительно, в главном потоке вполне могут сосуществовать несколько однотипных объектов, раз в 2 секунды получая сигнал от таймера и проверяя условие, а потом в случае отрабатывания условия отправлять запрос через QNetworkAccessManager. Теперь осталось разобраться, как сделать так чтобы эти объекты создавались при нажатии на одну и ту же кнопку, чтобы не делать отдельную кнопку под каждый объект, так как количество этих объектов плавающее, может быть от 0 до нескольких штук. Пока в голову приходит только такой вариант:

if (!worker1)
    {
        <код>;//создать объект worker1
        <код>;//соединить worker1 с таймером
        
    }
    else if (!worker2)
             {
                   <код>;//создать объект worker2
                   <код>;//соединить worker2 с таймером
             }
//и так несколько раз

Меня в принципе такой вариант устраивает, но может быть есть способ прикрутить инкремент к имени указателя на объект, или по другому как-то упростить код?

g3nt00user ()

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

rumgot ★★★★★ ()
Ответ на: комментарий от g3nt00user

Вопрос насчёт одной кнопкой несколько объектов для меня больше не актуален, так как если объявлять и создавать указатели на объекты в методе, который запускается по нажатию кнопки, как я хотел, то после завершения работы метода указатель прекратит существование, и будет утечка памяти, и к новому созданному объекту не будет доступа у таймера. Нужно объявлять все могущие понадобиться указатели во внешнем пространстве имён. А раз так, то нужно явно прописать все присваивания адресов объектов указателям на эти объекты.

Всем спасибо за помощь.

g3nt00user ()
Ответ на: комментарий от deep-purple

Возможно узким местом станет время ожидания ответа

Чтение ответа будет по сигналу readyRead или что-то такое, если ничего не пришло, то другие действия преспокойно себе будут выполняться. В чем здесь узкое место?

rumgot ★★★★★ ()
Ответ на: комментарий от rumgot

Забей, я просто как всегда о расширяемости думаю, так еще и 7-я бутылька пива. Я бы всеравно сделал в отдельном треде, ибо хрен его знает, что еще надумается понавесить.

deep-purple ★★★★★ ()

Для доступа к состоянию и результатам сразу нескольких потоков создай контейнер, содержащий неограниченное число объектов (в виде списка, вектора или чего тебе там удобнее).

Но, как здесь уже сказали, создавать огромное число потоков для выполнения достаточно лёгких и быстрых задач — не самая умная идея, т. к. накладные расходы на их создание могут превысить потенциальный выигрыш. Используй неблокирующие сокеты и select(), не забывая время от времени засыпать при помощи sleep(), чтоб зря не перегружать процессор. Если одновременных соединений может быть очень-очень много, то возможен компромисс: использование числа потоков по числу ядер, а внутри всё те же несколько соединений на каждый поток с использованием всё тех же неблокирующих сокетов и select. Но это надо тестировать на реальных данных, что будет быстрее.

aureliano15 ()
Ответ на: комментарий от ox55ff

Зачем тебе два worker? Они разные?

Каждый экземпляр worker'а получает свои параметры, подготавливает с использованием этих параметров запрос к серверу, ждёт выполнения условия и отправляет запрос. Несколько экземпляров нужно для одновременного выполнения нескольких таких отложенных запросов, ждущих выполнения условия.

g3nt00user ()