Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> работа с потоками, ограничение по к-ву 
:(
    Опции темы
uranpro
Дата 13.7.2009, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

Репутация: нет
Всего: 1



Добрый день!
есть проблема, нужно в цикле создавать потоки, не больше 100 штук, при выполнении кода, прога зависает:
Код

  property ThreadQty
  procedure CreateThread
  ...
  for i:=1 to 10000 do begin
    while ThreadQty>=100 do
      Sleep(10);
    CreateThread;
    end;


sleep должен слипить текущий поток(т.е. с которого его вызывали), почему он слипит все потоки ???
как реализовать ограничение ?


--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
kami
Дата 13.7.2009, 17:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(uranpro @  13.7.2009,  17:23 Найти цитируемый пост)
при выполнении кода, прога зависает

а не зависала бы - выдала бы StackOverflow. 
Судя по коду - там бесконечная рекурсия возникает. То есть, при вызове CreateThread 10000 раз вызывается она же. И там тоже самое. И так до бесконечности.
Не ясно, где меняется ThreadQty. 

Цитата(uranpro @  13.7.2009,  17:23 Найти цитируемый пост)
почему он слипит все потоки

почему все?
Текущий, который скорее всего и есть MainThread. C учетом того, что Delphi всю визуализацию делает в основном потоке - это более чем естественно. Но опять-таки, не ясно с ThreadQty.

Добавлено через 5 минут и 8 секунд
Чуть добавлю:
из-за рекурсивного бесконечного вызова процедуры приостанавливается выборка сообщений из очереди. Поэтому приложение и "зависает". И слипы тут ни при чем. Но включение в код Application.ProcessMesssages ничего хорошего не даст - просто до StackOverflow придется подождать подольше smile
PM MAIL WWW   Вверх
CodeMonkey
Дата 13.7.2009, 17:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



Существует ли в Windows ограничение в 2000 потоков на каждый процесс на самом деле? :
Цитата(http://kholeg.spaces.live.com/Blog/cns!D006ED9CB32B0F60!156.entry)

Но главный вопрос, который возникает, когда кто-то спрашивает: "Чему равно максимальное число потоков, которое может создать процесс?" таков: "А почему вы создаете так много потоков, что это становится актуально?"




--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
uranpro
Дата 13.7.2009, 17:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

Репутация: нет
Всего: 1



kami, поток сам себя убивает, с этим нет проблем, время работы потока в среднем 10мс.
с ThreadQty все нормально, это счетчик потоков, при создании потока +1, освобождении -1

почему все ? потому что прога зависает)
сказал уснуть гл.потоку, а уснули, по видимому, все =(

Добавлено через 3 минуты и 21 секунду
CodeMonkey, =) надо мне много потоков, сеть сканить гораздо быстрее получается!)

Добавлено через 4 минуты и 20 секунд
CodeMonkey, на шарпе/вб все нормально слипится. мне нужно на дельфе написать


--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
kami
Дата 13.7.2009, 17:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(uranpro @  13.7.2009,  17:47 Найти цитируемый пост)
 потому что прога зависает

В чем выражается это зависание?
Если в том, что не реагирует на мышь и клавиатуру, то еще раз повторюсь - это нормально. Потому что вы не обратили внимание на первую часть моего поста: у вас в коде БЕСКОНЕЧНАЯ РЕКУРСИЯ, лочащая основной поток.
PM MAIL WWW   Вверх
uranpro
Дата 13.7.2009, 18:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

Репутация: нет
Всего: 1



kami, я не говорил, что это бесконечная рекурсия)
>поток сам себя убивает, с этим нет проблем, время работы потока в среднем 10мс
Код

procedure TScanThr.Execute;
begin
  try
    P:=TPing.Create(nil);
    P.Address:=Adrr;
    P.Timeout:=100; // раз
    if P.Ping = 1 then
      Synchronize(Add);
  finally
    P.Free;
    end;
  Synchronize(ThrEnd);
  Terminate;  // два
end;


      ScanThr:=TScanThr.Create(true);
      with ScanThr do begin
        FreeOnTerminate:=true; // три =)
        ...
        Resume;
        end;


Это сообщение отредактировал(а) uranpro - 13.7.2009, 18:08


--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
kami
Дата 13.7.2009, 18:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(uranpro @  13.7.2009,  18:04 Найти цитируемый пост)
я не говорил, что это бесконечная рекурсия

а я и не говорил, что это сказали вы. И говорил я за первоначальный код.

Цитата(uranpro @  13.7.2009,  17:23 Найти цитируемый пост)

property ThreadQty  
procedure CreateThread  // обратим внимание на название процедуры.
...  
for i:=1 to 10000 do // организуем цикл до 10000
  begin    
    while ThreadQty>=100 do      
      Sleep(10);    // поспим чуть-чуть
    CreateThread;    // и ВЫЗОВЕМ СЕБЯ ЖЕ 10000 раз. 
    // В результате опять организуется (уже вложенный) цикл, в котором ОПЯТЬ вызываем СЕБЯ ЖЕ 10000 раз
    // и так далее до бесконечности
  end;


Добавлено через 1 минуту и 14 секунд
Где выход из этой рекурсии?
Я его не наблюдаю.
PM MAIL WWW   Вверх
uranpro
Дата 13.7.2009, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

Репутация: нет
Всего: 1



kami, я видимо плохо объяснил) 
строками
Код

property ThreadQty  
procedure CreateThread

я хотел показать, что определил свойства и методы, с ними все ок.

а цикл в др. методе

Это сообщение отредактировал(а) uranpro - 13.7.2009, 18:13


--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
kami
Дата 13.7.2009, 18:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(uranpro @  13.7.2009,  18:12 Найти цитируемый пост)
а цикл в др. методе

ну дык... из кода этого-то не видно. Ограничил бы цикл begin-end ом, было бы понятнее.

Теперь вроде ясно.
Итак.
Исходная процедура ждет, пока не ликвидируется какой-нибудь поток, бо их количество стало больше критического.
Код

while ThreadQty>=100 do
  Sleep(10);

Обратим внимание, что этот цикл не предполагает обработку сообщения, он просто ЖДЕТ.

Один из потоков закончил свою работу и хочет удалиться (но пока присутствует!!!)
Пытается сообщить об этом основной программе:
Код

Synchronize(ThrEnd);

В Delphi метод Synchronize действует через отправку сообщения основному потоку, и ожидает, пока это сообщение (и содержимое метода Synchronize) не будет отработано.

Смотрим, что получилось:
основной поток в бесконечном цикле, не предполагающем обработку сообщений.
Дополнительный поток перед завершением отправил сообщение и ждет, пока главный поток выполнит его метод синхронизации. 
Цейнтнот, однако:
один не может, а второй ожидает окончания этого "не может". И конца и края их ожиданию не видно...

Добавлено через 4 минуты и 17 секунд
Предлагаю:
вместо Synchronize использовать отправку основному потоку сообщения через PostMessage, что ликвидирует задержки и развяжет потоки друг от друга.
Ограничение:
в обработчике этого сообщения нельзя будет использовать никакие ссылки и переменные, содержащие созданные TThread-ы

Добавлено через 13 минут и 38 секунд
второй вариант:
вместо Sleep поставить Application.ProcessMessages.
Но не советовал бы - навскидку не скажу, но были у меня какие-то трудноуловимые заморочки, связанные с Application.ProcessMessages в многопоточном приложении.
PM MAIL WWW   Вверх
uranpro
Дата 13.7.2009, 18:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 571
Регистрация: 7.5.2008
Где: Moscow city

Репутация: нет
Всего: 1



kami, Спасибо! я-то думал))


--------------------
I want a perfect soul
PM MAIL ICQ   Вверх
CodeMonkey
Дата 14.7.2009, 09:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



Цитата(uranpro @  13.7.2009,  17:47 Найти цитируемый пост)
CodeMonkey, =) надо мне много потоков, сеть сканить гораздо быстрее получается!)

Быстрее всего сеть сканить в асинхронном режиме числом потоков, близким к числу процессоров.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Romikgy
Дата 22.7.2009, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 26
Всего: 146



Цитата(kami @  13.7.2009,  17:27 Найти цитируемый пост)
В Delphi метод Synchronize действует через отправку сообщения основному потоку, и ожидает, пока это сообщение (и содержимое метода Synchronize) не будет отработано.

хммм
Код

class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord);
var
  SyncProc: TSyncProc;
begin
  if GetCurrentThreadID = MainThreadID then
    ASyncRec.FMethod
  else
  begin
{$IFDEF MSWINDOWS}
    SyncProc.Signal := CreateEvent(nil, True, False, nil);
    try
{$ENDIF}
{$IFDEF LINUX}
      FillChar(SyncProc, SizeOf(SyncProc), 0);  // This also initializes the cond_var
{$ENDIF}
      EnterCriticalSection(ThreadLock);
      try
        if SyncList = nil then
          SyncList := TList.Create;
        SyncProc.SyncRec := ASyncRec;
        SyncList.Add(@SyncProc);
        SignalSyncEvent;
        if Assigned(WakeMainThread) then
          WakeMainThread(SyncProc.SyncRec.FThread);
{$IFDEF MSWINDOWS}
        LeaveCriticalSection(ThreadLock);
        try
          WaitForSingleObject(SyncProc.Signal, INFINITE);
        finally
          EnterCriticalSection(ThreadLock);
        end;
{$ENDIF}
{$IFDEF LINUX}
        pthread_cond_wait(SyncProc.Signal, ThreadLock);
{$ENDIF}
      finally
        LeaveCriticalSection(ThreadLock);
      end;
{$IFDEF MSWINDOWS}
    finally
      CloseHandle(SyncProc.Signal);
    end;
{$ENDIF}
    if Assigned(ASyncRec.FSynchronizeException) then raise ASyncRec.FSynchronizeException;
  end;
end;



--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0679 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.