Как контролировать количество запущенных Thread ?

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Как контролировать количество запущенных Thread ?

Сообщение and_rivne » 22.08.2018 12:04:33

Порекомендуйте решение, чтобы держать количество потоков под контролем.
В главном модуле программы, при потребности, создаю поток, который должен отработать и сам "умереть" (схема работает):
Код: Выделить всё
InetThrd := TThread.Create();
InetThrd.Start;

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

Из решений нашел только два:
1. Самому контролировать количество запущенных потоков и организовать очередь (как-то влом изобретать велосипед)
2. Использовать ProcThreadPool.DoParallel из http://wiki.freepascal.org/Parallel_procedures (не уверен что это то что мне нужно)
and_rivne
новенький
 
Сообщения: 20
Зарегистрирован: 09.12.2011 13:40:42

Re: Как контролировать количество запущенных Thread ?

Сообщение olegy123 » 22.08.2018 12:14:23

and_rivne писал(а):Но в какой то момент натыкаюсь на ошибку "не достаточно памяти" при создании нового потока.
что там с памятью делаете что заканчивается?

and_rivne писал(а):Хочу ограничить количество, например 5, а все остальные потоки пусть ждут.
вам нужен семафор.
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Как контролировать количество запущенных Thread ?

Сообщение and_rivne » 22.08.2018 12:20:26

что там с памятью делаете что заканчивается?

Судя по документации, там что не делай, но количество одновременно запущенных потоков ограничено. У меня затыкается, приблизительно, на 120 штук.

вам нужен семафор.

Есть готовые решения от лазаруса?
and_rivne
новенький
 
Сообщения: 20
Зарегистрирован: 09.12.2011 13:40:42

Re: Как контролировать количество запущенных Thread ?

Сообщение serbod » 22.08.2018 14:44:24

Примерно так, это общая идея, а развить можно по-своему:

Код: Выделить всё
var GlobalThreadCount: Integer;

procedure TThread.AfterConstruction();
begin
  inherited;
  Inc(GlobalThreadCount);
end;

procedure TThread.BeforeDestruction();
begin
  Dec(GlobalThreadCount);
  inherited;
end;

Аватара пользователя
serbod
постоялец
 
Сообщения: 449
Зарегистрирован: 16.09.2016 11:03:02
Откуда: Минск

Re: Как контролировать количество запущенных Thread ?

Сообщение olegy123 » 23.08.2018 15:41:43

and_rivne писал(а):Есть готовые решения от лазаруса?

есть документация
http://prog-example.ru/mnogopotochnost.html

and_rivne писал(а):. У меня затыкается, приблизительно, на 120 штук.
у меня было больше 20000, полет был нормальный.
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Как контролировать количество запущенных Thread ?

Сообщение Ichthyander » 23.08.2018 22:16:36

and_rivne писал(а):Судя по документации, там что не делай, но количество одновременно запущенных потоков ограничено. У меня затыкается, приблизительно, на 120 штук.

У меня было также. Больше 120 штук не создавалось. Как я решил, на основании https://bugs.freepascal.org/view.php?id=17755
Уже не помню точно, но проблему решил установкой ключа -Cs (Stack Size в свойствах проекта). После этого потоков и по 1000 и больше создается.
Теперь важный момент: в последних версиях Lazarus у меня все работает и без установки этого ключа. Хотя вот мне пришло в голову сейчас: может дело было в битности системы или версии ОС Виндоус?
Аватара пользователя
Ichthyander
энтузиаст
 
Сообщения: 668
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

Re: Как контролировать количество запущенных Thread ?

Сообщение olegy123 » 24.08.2018 04:10:40

Ichthyander писал(а):Хотя вот мне пришло в голову сейчас: может дело было в битности системы или версии ОС Виндоус?
да там есть ограничения, но обычному пользователю их нереально достичь - размерность там в 32битах в x86 и 64бита в x86_64. В линухе сетевые параметры подходят для 100мб/с, с 1Gb/s нужно их подкручивать.

Иначе всякие торрент-качалки, игры, сайты, инженерные задачи испытывали трудности.
У автора темы скорее либо задача неправильно оформлена, либо просто протечка памяти сразу образовала залив.
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Как контролировать количество запущенных Thread ?

Сообщение and_rivne » 09.10.2018 13:26:51

Да, скорее всего у меня не правильная схема работы с сокетами.
У меня получается на каждый коннект клиента создается отдельный поток. Так во все примерах в synapse.

Код: Выделить всё
Socket.CreateSocket;//создаем новый сокет
  //связываем сокет с локальным адресом
  Socket.Bind(Socket.LocalName,'57778');
  if Socket.LastError=0 then //связываение с локальным адресом прошло успешно
     Socket.Listen //переходим в режим ожидания
  else
    raise Exception.Create(Socket.LastErrorDesc);//ошибка связывания - показываем её пользователю
  repeat
     if Socket.CanRead(100) then //можем произвести чтение
       begin
         //получаем дескриптор сокета и создаем новую нить для клиента
         T:=TClientThread.Create(True,Socket.Accept);
         //Сохраняю нить с сокетом, чтобы потом отправить ответ
         ThreadList.Add(pointer(T));
         //запускаем нить на выполнение
         T.Start;
       end;
   until Terminated;


Так вот и вопрос в том, как подключать 100 клиентов и не создать 100 потоков.
И что бы клиенту потом по ClientID можно было бы отправить ответ.

Я делаю так:
Код: Выделить всё
cln := TClientThread(ThreadList.Items[ClientID]);
cln.Socket.SendString("answer test");
and_rivne
новенький
 
Сообщения: 20
Зарегистрирован: 09.12.2011 13:40:42

Re: Как контролировать количество запущенных Thread ?

Сообщение MysticCoder » 09.10.2018 19:15:59

Ichthyander писал(а):проблему решил установкой ключа -Cs (Stack Size в свойствах проекта). После этого потоков и по 1000 и больше создается.

это если тебе по потоку на клиента надо. если надо по нормальному делать то гугли асинхронные сокеты.
MysticCoder
постоялец
 
Сообщения: 154
Зарегистрирован: 14.09.2013 00:20:28

Re: Как контролировать количество запущенных Thread ?

Сообщение Ichthyander » 10.10.2018 11:38:17

MysticCoder писал(а):это если тебе по потоку на клиента надо. если надо по нормальному делать то гугли асинхронные сокеты.

Если это мне, то в моем случае это не сервер вообще был.
and_rivne писал(а):Так вот и вопрос в том, как подключать 100 клиентов и не создать 100 потоков.
И что бы клиенту потом по ClientID можно было бы отправить ответ.

У Вас сервер держит соединение после отправки и приема сообщений и не закрывает его? Если так, то да, как сказали выше асинхронные сокеты. Потоки наверное можно (да, наверное, и нужно) закрывать[ и освобождать] после приема-отправки сообщений, "храня" дескриптор сокета основному потоку. Для клиентской части я так и делал, но для серверной нужно будет использовать сокеты в асинхронном режиме
Аватара пользователя
Ichthyander
энтузиаст
 
Сообщения: 668
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

Re: Как контролировать количество запущенных Thread ?

Сообщение olegy123 » 11.10.2018 13:01:45

and_rivne писал(а):И что бы клиенту потом по ClientID можно было бы отправить ответ.

Я делаю так:
Код: Выделить всё
cln := TClientThread(ThreadList.Items[ClientID]);
cln.Socket.SendString("answer test");
Все верно.. еще бы добавить синхронизацию

and_rivne писал(а):Так вот и вопрос в том, как подключать 100 клиентов и не создать 100 потоков.
В линухе есть epoll, смысл в том чтобы ядро линуха оптом метила дискрипты в которых есть что то новенькое и отдавала этот список приложению.. а приложение уже само однозадачно или многозадачно рассматривала этот список..
по тестам пишут что выйгрыш есть при от 10000 подключений..
до 10000 лучше использовать классику -> одно подключение - выделенная нить.

Добавлено спустя 8 минут 32 секунды:
MysticCoder писал(а):это если тебе по потоку на клиента надо. если надо по нормальному делать то гугли асинхронные сокеты.
не все задачи асинхронные.. Клиенту/сервису лучше крепко поспать, получить ответ и поработать..
Асинхронные выгоднее использовать в потоках, стримах, там где нужно тонны переслать информации. Когда простой дорого стоит.
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Как контролировать количество запущенных Thread ?

Сообщение and_rivne » 12.10.2018 12:22:11

olegy123
Все верно.. еще бы добавить синхронизацию

С этого места поподробней пожалуйста.
and_rivne
новенький
 
Сообщения: 20
Зарегистрирован: 09.12.2011 13:40:42

Re: Как контролировать количество запущенных Thread ?

Сообщение olegy123 » 12.10.2018 14:38:25

Создаются процессы, если они сами по себе живут, никому не мешают, то синхронизации можно и не задумываться..
Но если необходимо им использовать общественные места, допустим регистратуру.. то нужен "турникет". Для этого есть TCriticalSection(мютекс) / семафоры ..
Всякие TEvent (запуск по событию) и прочее..
http://www.realcoding.net/articles/poto ... elphi.html

Добавлено спустя 9 минут 6 секунд:
TCriticalSection - выделяет участок где будет находится всегда один поток, остальные при входе уснут. Вот когда этот поток выйдет, другой один зайдет..
Семафоры - позволяют сразу зайти определенному кол-ву..
TEvent - нужны для "запуска" "спящего" процесса..

Добавлено спустя 15 секунд:
uses syncobj;
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Как контролировать количество запущенных Thread ?

Сообщение and_rivne » 12.10.2018 15:27:21

Спасибо за наводку!
Маленькое уточнение:
Если в одном потоке TList наполняется, а в другом циклом анализируется - что использовать?
Потоков на добавление один, а тех кто "крутить" несколько.
and_rivne
новенький
 
Сообщения: 20
Зарегистрирован: 09.12.2011 13:40:42

Re: Как контролировать количество запущенных Thread ?

Сообщение Ichthyander » 12.10.2018 15:35:06

Либо потокобезопасные списки, либо обеспечивать синхронизацию самостоятельно. Как минимум данные могут оказаться неактуальными (при условии, что один поток только записывает). А если оба, то результат может оказаться еще более плачевным

Добавлено спустя 2 минуты 3 секунды:
Пример потокобезопасного списка https://www.freepascal.org/docs-html/rt ... dlist.html
Аватара пользователя
Ichthyander
энтузиаст
 
Сообщения: 668
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 33

Рейтинг@Mail.ru