Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Загрузчик на idHTTP зависает при загрузке страниц


Страницы:   1 2

Pcrepair ©   (2013-01-07 03:14:00) 

Добрый день. Есть код загрузчика страниц(вызывается в поток):

function TLoader.LoadHtmlCode(const PageUrl: String):string;
var
ErrorData:string; (*ответ сервера в тестовом виде*)
ResponseCode:integer; (*ответ сервера в виде кода ошибки*)
begin
  try
    (*---------настройка параметров закачки-----------*)
    FIdHttp.Request.UserAgent:=GetRandomUserAgent; (*получаем случайное значение Юзер-Агент*)
    FIdHttp.Request.AcceptLanguage:='ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3'; (*вроде нужно*)
    FIdHttp.Request.AcceptCharSet:='windows-1251,utf-8;q=0.7,*;q=0.3'; (*вроде нужно*)
    FIdHttp.ConnectTimeout:=10000;
    FIdHttp.ReadTimeout:=10000;
    FIdHttp.IOHandler:=FSSL;
    FIdHttp.HandleRedirects:=True;
    Result:=AnsiLowerCase(FIdHttp.Get(PageUrl));
      except
        Result:=PageUrl;
        (*тут вызов ПРОЦ для записи ответа сервера и УРЛ в лог*)
      end;
     Exit;  (*выход из функции. в РЕЗУЛЬТАТ содержится последнее значение*)
  end;
end;

1. При высокой скорости трафика все работает нормально:
- загрузка 100 УРЛ за 20...25 сек (10 потоков одновременно)
- никаких утечек памяти
практически все как предначертано работает
2. При наличие потребителя трафика(другой РС в сети с работающим ТОРРЕНТ, источник интернета - роутер 3 мбит\сек):
- загрузка 97...100 УРЛ за 60...120 сек
- один или два потока зависают(есть на форме индикатор числа работающих потоков)при закачке УРЛ и могут висеть часами, пока не закрыть программу
- никакой зависимости от УРЛ нет, в одном тесте одни УРЛ не закачиваются в другом другие
- еще одна особенность: в логе фиксируется ответ сервера. при наличие конкурента на трафик от 10 до 30 УРЛ не загружаются(то же различные, от теста к тесту), хотя ответ сервера = 200 (ну это не самая большая проблема, скоро будет добавлен код перезакачки УРЛ), но о чем то этот факт говорит?

Внимание! Вопросы:
1. в чем причина такого поведения TidHttp?
возможно надо что то настроить в параметрах загрузчика?
2. возможно ли ввести в поток загрузчика таймер типа:

procedure TLoader.Execute;
begin
 CallTimer;
 FIdHttp.Get(PageUrl);
end;

procedure TLoader.CallTimer;
begin
 (*тут реализация таймера на 100 сек, но на чем? TTimer явно не подойдет*)
  Событие OnTimer вызывает
  FIdHttp.Socket.Close; (*если через 100 сек страница не закачается и поток не сдохнет
  принудительно закрыть idHTTP, поток после тоже закроется*)
  может кто подскажет реализацию таймера, на чем бы его сделать?
end;


почитал на форумах что нашел, похоже таймер единственный вариант решить эту проблему


Anatoly Podgoretsky   (2013-01-07 21:36:00) [21]

> sniknik  (07.01.2013 21:13:16)  [16]

C азов это очень сложно.


Pcrepair   (2013-01-07 21:30:00) [22]

да ничего такого
просто программа должна выдавать результат с мнимимальным временем отклика

> Ну так и установи ReceiveTimeout и ConnectTimeout = 300
> сек !
>
> Через 300 сек получишь отлуп в виде EIdReadTimeout или EIdConnectTimeout
> - и делай в обработчике исключения нужные тебе телодвижения.
>


так и установил в 100 сек. но не грохается
а ссылка интересная. получается это все мелкие косячки инди


> почему нет? ты проверял, что он там делает все это время?

а ничего не делает. просто висит. и как это можно проверить? если GET так и не закончил работу.


sniknik   (2013-01-07 21:15:00) [23]

кстати, а что там перекачивается, что аж 5 мин требуется ждать?


sniknik   (2013-01-07 21:13:00) [24]

> исключения просто небыло
не было или ты его не видел? т.к. благополучно проигнорировал (в приведенном коде).
"позиция страуса" - не вижу значит не существует. закрою глаза значит не бывает.

p.s. ты на самом деле ни хрена не понимаешь? может тебе не с потоков, с основ начать? ну там, объекты, операции, события, исключения...

> Через 300 сек получишь отлуп
не все так просто, бывают варианты (версия/ssl) неправильного "тайминга"
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1287562673&n=4
но на "крайняк" получит через 900 сек (или ставить 100 сек).


Сергей М.   (2013-01-07 20:15:00) [25]


> вот и надо через 300 сек поток принудительно грохнуть


Ну так и установи ReceiveTimeout и ConnectTimeout = 300 сек !

Через 300 сек получишь отлуп в виде EIdReadTimeout или EIdConnectTimeout - и делай в обработчике исключения нужные тебе телодвижения.


brother   (2013-01-07 20:12:00) [26]

> ага метод продолжает выполнение, час продолжает. два продолжает

почему нет? ты проверял, что он там делает все это время?


Pcrepair   (2013-01-07 20:10:00) [27]

Что значит "не продолжает ждать" ? = продолжает ждать
ага метод продолжает выполнение, час продолжает. два продолжает
вот и надо через 300 сек поток принудительно грохнуть, всему есть разумный предел


Сергей М.   (2013-01-07 19:58:00) [28]


> исключения просто небыло


Если исключения (не важно какого) не было, значит метод либо продолжает выполнение либо успешно выполнен.


Сергей М.   (2013-01-07 19:56:00) [29]


> нету ошибки
> метод GET просто не продолжает что то ждать от сервера


Что значит "не продолжает ждать" ?
Прямо так и говорит "не хочу больше ждать, я устал" ?


Pcrepair   (2013-01-07 19:36:00) [30]

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

так ведь нету ошибки
метод GET просто не продолжает что то ждать от сервера
я вводил обработку исключения E:EIdHTTPProtocolException но исключения просто небыло.
логика событий крайне простая:
- нажимаем кнопку "ПУСК"
- вызывается основной поток управления потоками(это чтоб таймер на форме не подвисал), получает список УРЛ(ну до 1000)
- основной поток запускает цикл создания потоков закачки(внутри экземпляр idhttp) +1 в счетчик потоков
- потоки закачивают и передают результат в ГП и стетчик потоков уменьшают на 1
- основной поток считает сколько потоков в наличии чтоб больше 10 не было, один закончил работу, дозапускается еще один
но это все делается без учета ИД потоков, просто есть ГП типа ЧИСЛО

Всетаки проблема в idHTTP. была слабая надежда что можно как то в самом экземпляре потока все сделать. так чтобы отработал 300 сек и отключился, неважно отработало ли idhttp.get


sniknik   (2013-01-07 16:25:00) [31]

> теория интересная
это не теория... это аксиома (факт). вот если бы ты вместо сказанного исправил код, отловил, и привел сюда реально происходящую ошибку... тогда бы можно было сказать что обучение туго, но идет.
а так как нет, то - "необучаем".

> везде пишут что TTimer в потоке лучше не использовать
смысла в нем там нет, это же поток. и сделать его там мало, нужно (главное) цикл сообщений организовать ... где ты встретишься с теми же проблемами от которых говоришь хочешь избавится. и что дальше? еще поток, в потоке, запущенном из потока диспетчера потоков?
лучше бы логику событийную пытался понять, а не писал "линейно" впихивая везде потоки.

DVM ©   (07.01.13 15:23) [6]
>> Pcrepair ©
> 1. У IdHTTP есть свойства ReadTimeout и ConnectTimeOut. Это первое. Они позволят при недоступном или не отвечающем сервере не висеть вечно.
у него они используются, эти свойства..., проблема не в них а где то в ЕГО коде, который типа "много, но работает" и поэтому можно не приводить.


Медвежонок Пятачок   (2013-01-07 15:27:00) [32]

везде пишут что TTimer в потоке лучше не использовать
выражай мысли поточнее, если не сложно


Ты же кровь из носу хотел создать именно таймер и именно в потоке.

как же сделать таймер в потоке? никто не знает

Теперь тебе сказали как создать таймер в потоке.


DVM   (2013-01-07 15:26:00) [33]


> Pcrepair ©


> 2. не надо предлагать как лучше. идет процесс обучения.
> в ланный момент хочю попробовать запустить таймер в ПОТОКЕ
> итак еще разок:
> как же сделать таймер в потоке? никто не знает!?

все знают, кто хоть раз вместо форума открывал справку от TTimer или раздел MSDN где говорится про функцию SetTimer. Но нужен ли там тебе таймер? Тем более что его работа в доп потоке будет блокирована тем же блокирующим Indy


DVM   (2013-01-07 15:23:00) [34]


> Pcrepair ©

1. У IdHTTP есть свойства ReadTimeout и ConnectTimeOut. Это первое. Они позволят при недоступном или не отвечающем сервере не висеть вечно.
2. Если поток, осуществляющий закачку по каким то причинам повис на очень-очень медленном ответе сервера, то закачку всегда можно прервать сделав сокету от TidHTTP Close, но из другого потока (предварительно убедившись, что сокет вообще есть).


Pcrepair   (2013-01-07 15:23:00) [35]

какого таймера конструктор?
везде пишут что TTimer в потоке лучше не использовать
выражай мысли поточнее, если не сложно


Медвежонок Пятачок   (2013-01-07 15:05:00) [36]

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


Pcrepair   (2013-01-07 13:59:00) [37]


> блин, чего я распинаюсь, ты же "необучаем"... может просто
> - закрывай коннект (FIdHttp.Disconnect) в LoadHtmlCode перед
> последним end;.

теория интересная, но.....
1. подобный вопрос уже обсуждался на разных форумах, пришли к выводу что это текущий глюк ИНДИ(GET не отрабатывает при некоторых условиях, в данном случае из за маленькой скорости трафика и некоторых настроек некоторых веб-серверов, которые не отдают контент и не разрывают соединение)
2. не надо предлагать как лучше. идет процесс обучения. в ланный момент хочю попробовать запустить таймер в ПОТОКЕ
итак еще разок:
как же сделать таймер в потоке? никто не знает!?


sniknik   (2013-01-07 13:13:00) [38]

кстати, т.к. ошибка игнорируется т.е. блокируется и дает "развернуть цепочку" то возможно "зависание" это попросту ожидание реакции (ответа или эксепта) где нибудь в связанных компонентах (например FSSL).
... есть еще одно на что оно среагирует, на закрытие коннекта, и не в вынесенном таймере, а прямо в коде после исполнения/глюка.

блин, чего я распинаюсь, ты же "необучаем"... может просто - закрывай коннект (FIdHttp.Disconnect) в LoadHtmlCode перед последним end;.


sniknik   (2013-01-07 13:03:00) [39]

внимание! ответы:
1: у тебя ошибка в программе... где хз. т.к. если убрать всю "мишуру" из "примера проблемного кода" останется только IdHttp.Get с игнорированием ошибки от него (из чего, и твоего "психо портрета", следует - что это за ошибка мы так никогда не узнаем...)
2: во первых возможно, во вторых не нужно... у тебя там и так (ИМХО) перебор с потоками. они не панацея они инструмент. а ты их пихаешь/пытаешься куда не попадя. если так уж хочется таймер то поставь его с главной формы.... один на все, в основном потоке, он же у тебя свободен, нет? сделать диспетчеризацию с проверкой таймаута можно и оттуда.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо