Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 20.04.2014, 00:53   #1
xrob
Форумчанин
 
Регистрация: 18.10.2010
Сообщений: 419
По умолчанию TThread и WaitForSingleObject

Добрый вечер, друзья =)
У меня возникли проблемы, которые я даже затрудняюсь внятно описать.
Пока пытаюсь разобраться самостоятельно, но не могли бы вы прокомментировать,
правильно ли я использую указанные штуки.

Я делаю компонент который должен скачать указанную ссылку.
Непосредственно для скачивания используется компонент TidHTTP (запрос Get).
Задумка такова:
нужно реализовать систему, работу которой можно было бы
прекратить, независимо от ее состояния
(чтобы в случае чего прога не повисала намертво).
ИМЕННО для этого создается поток, в котором и выполняются TidHTTP.Get(link)

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


Но при этом основной код не должен выполняться параллельно с потоком,
т.е. после запуска потока надо дождаться завершения его работы и только
после этого продолжить выполнение основного кода.
Для этого я использую функцию WaitForSingleObject, которая ждет событие, которое активируется в конце работы потока.

алгоритм такой:

1. создаем событие
2. создаем и запускаем поток
3. ждем "чуда"
4. поток подходит к концу и активирует "чудо"
5. продолжаем основной код

вот как реализовано:

1. Event:=CreateEvent(nil, True, False, nil); // создаем событие (ручной сброс, сброшено)
2. TR:=TThread.Create; // создаем и запускаем поток
TR.Resume;
3. WaitForSingleObject(Event, 5000); // ждем чуда (при этом поток по-идее работает паралельно)

4. код, выполняемый в потоке:
procedure Execute;
begin
TidHTTP.Get(link); // выполняем необходимые действия
PulseEvent(Event); // активируем "чудо"
end;


По-моему здесь все логично, но возникают проблемы, причем с определенной закономерностью:
как правило выполняется пара тысяч запросов, а потом что-то слетает и все остальные запросы
проскакивают мгновенно - как будто "чудо" активируется сразу при запуске потока.
Я грешил на то, что это из-за того, что не удаляю событие после использования,
я это исправил, но проблема не исчезла.
Что касается всего остального - весь объект удаляется и создается по-новой на каждый запрос.

В процессе ковыряния в проблеме пробовал такой вариант:
вызывать PulseEvent(Event); не в конце потока, а в процедуре по завершении (OnTerminate).
в результате поток не начинал свою работу, пока не пройдет таймаут ожидания ( 5000 ms ).

В общем скажите, что я не учел?
Может я не знаю каких-то нюансов?

Последний раз редактировалось xrob; 20.04.2014 в 13:50.
xrob вне форума Ответить с цитированием
Старый 20.04.2014, 02:04   #2
northener
ПШП
Участник клуба
 
Регистрация: 15.07.2013
Сообщений: 1,872
По умолчанию

Цитата:
Для этого создается поток, в котором и выполняются TidHTTP.Get(link)
Но при этом основной код не должен выполняться параллельно с потоком,
т.е. после запуска потока надо дождаться завершения его работы
Вот и скажите мне нафига тут доппоток?
northener вне форума Ответить с цитированием
Старый 20.04.2014, 13:54   #3
xrob
Форумчанин
 
Регистрация: 18.10.2010
Сообщений: 419
По умолчанию

northener, вы полностью читали первый пост, или частично?
специально для вас, и всех, кто не понимает зачем здесь поток,
я выделил место, в котором объясняется зачем.

Но как бы там ни было, вопрос то все-таки не про поток, а про
CreateEvent, WaitForSingleObject и PulseEvent: что я делаю не так?


Для тех, кто считает, что я "хочу странного", объясню ход своих мыслей.
Я исхожу из двух фактов:
1. TidHTTP может зависнуть намертво.
2. Обломы допустимы, по прога должна работать нисмотря ни на что.

представьте такую ситуацию:
вам необходимо 100 раз выполнить следующую процедуру:

procedure FateChallenge;
var
c,d:integer;
begin
d:=Random(1);
if d=0 then c:=5;
if d=1 then while true do begin end;
end;

есть смельчаки?

Последний раз редактировалось xrob; 20.04.2014 в 14:06.
xrob вне форума Ответить с цитированием
Старый 20.04.2014, 13:56   #4
eoln
Старожил
 
Аватар для eoln
 
Регистрация: 26.04.2008
Сообщений: 2,645
По умолчанию

А может чуда и нет?
Если такая закономерность наблюдается при достаточно большом запуске потоков, то предположу следующее. Помню в старом Паскале была такая фишка - если выделять память, а потом её освобождать, то скоро память кончается из-за того, что она не возвращалась в кучу. Учитывая это, можно предположить, что и в Delphi (а там свой менеджер памяти) есть эта проблема. Не скажу точно, но причина может быть в том, что API функции и дельфийский потоки используют разные менеджеры памяти что и приводит к утечке памяти, невозможности создать событие по причине ограничения их числа или чего-то подобного. Вобщем надо смотреть в сторону памяти чем-то вроде http://technet.microsoft.com/en-us/s...rnals/dd535533
Кстати, зачем пересоздавать всё каждый раз? Пусть будет програма(основной поток) и ещё один поток (для загрузки). И переключаться между ними сигналами или любым другим известным способом.
Я инди почти не использую, но (если память не изменяет) там есть антифриз, который не замораживает форму при скачивании файла. Правда, говорят с ним что-то не так
eoln вне форума Ответить с цитированием
Старый 20.04.2014, 14:13   #5
xrob
Форумчанин
 
Регистрация: 18.10.2010
Сообщений: 419
По умолчанию

eoln, спасибо, вы подкинули интересную идею, если предположить, что вы правы, то гармонично это вписывается в ситуацию.

у меня запрос идет в try и получается так,
что я создаю TidHTTP, а он не создается, потому что памяти не хватает,
а потом я в try пробую делать запрос, соответственно это мгновенно
заканчивается провалом.

+ к тому же, стоит перезапустить прогу - все снова работает.

полез проверять теорию =)

а по поводу антифриза я, конечно, точно не знаю,
но предполагаю, что он работает так:
while true do Application.ProcessMessages; =D

Последний раз редактировалось xrob; 20.04.2014 в 14:18.
xrob вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Не срабатывает waitforsingleobject peeper Общие вопросы Delphi 2 28.11.2013 16:10
При освобождении обьекта TThread, он вешает всю программу. При этом код Execute у TThread уж выполнился.. Человек_Борща Общие вопросы Delphi 23 30.11.2011 09:18
Многопоточность showmodal и WaitForSingleObject bulldog5293 Общие вопросы Delphi 24 24.01.2011 18:46
WaitForSingleObject besserebrenik Win Api 3 15.02.2010 22:40
WaitForSingleObject в Delphi 2009 Хамяг Win Api 11 03.12.2009 09:06