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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 16.08.2011, 18:55   #1
Anfall
Форумчанин
 
Регистрация: 10.02.2009
Сообщений: 181
По умолчанию Потоки+idttp

Всем доброго времени суток.

Знаю, что тема уже изъезженная, но просьба помочь разобраться.

У меня в программе по определенному событию происходит связь с неким сервером через idhttp. Просходить это должно в фоне. Т е пользователь работает в моей программе, а она сама когда нужно посылает данные серверу по определенному событию. Все бы ничего, но если интернета нет, то форма подвисает секунд на 30. Антифриз не помогает. Поэтому было решено засунуть это в поток.

Примерно так:

Код:
type
  TSomeThread = class(TThread)
  private
    var1:string;
    var2:string;
  public
     procedure Execute; override;
     constructor Create(Avar1:string;Avar2:string);
  end;

{------------}


constructor TSomeThread.Create;
begin
 inherited Create(true);
 var1:=Avar1;
 var2:=Avar2;
 FreeOnTerminate:=true;
 Resume;
end;

procedure TSomeThreadExecute;
begin
  //some actions with IDHTTP
  Terminate;
end;
В общем все работает. Но в чем загвоздка. Событие, по которому создается поток может происходить сколько угодно раз и разное время.

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

Вот такая проблема. В общем у меня пару набросков есть. Но по-моему они все некорректные. Как это сделать правильно, без утечек?

Заранее благодарен.
Anfall вне форума Ответить с цитированием
Старый 16.08.2011, 19:47   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

создаете Tidhttp в конструкторе потока(соответственно объявляете как поле класса) а в деструкторе уничтожаете.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 16.08.2011, 20:32   #3
Anfall
Форумчанин
 
Регистрация: 10.02.2009
Сообщений: 181
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
создаете Tidhttp в конструкторе потока(соответственно объявляете как поле класса) а в деструкторе уничтожаете.
Ну это понятно. Я не совсем о том.
Есть событие по которому создается поток. Суть, что если уже есть созданный поток, который еще работает, надо его корректно завершить и создать новый. Как это делать правильно?

Вот что примерно происходит по событию:

Код:
SomeThread:=TSomeThread.Create(true);
SomeThread.Resume;

Последний раз редактировалось Anfall; 16.08.2011 в 20:39.
Anfall вне форума Ответить с цитированием
Старый 16.08.2011, 20:38   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Надо сделать так, что если поток уже существует, то корректно остановить его (с корректным очищением IDHTTP) и создать новый.
Сделай глобальную переменную потока (или свойство формы), в нее создавай поток, и при каждом создании проверяй не создано ли в ней уже что-то (не указывает ли она на еще не отработавший поток). Если переменка эта не nil то завершай ее поток.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 16.08.2011, 20:49   #5
Anfall
Форумчанин
 
Регистрация: 10.02.2009
Сообщений: 181
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Сделай глобальную переменную потока (или свойство формы), в нее создавай поток, и при каждом создании проверяй не создано ли в ней уже что-то (не указывает ли она на еще не отработавший поток). Если переменка эта не nil то завершай ее поток.
Спасибо. Уже думал так.
Но проблема-то в то что, а как толково завершить поток? Если б там был бы какой-то простой цикл, то можно было бы сделать:
Код:
Sometread.terminate.
А внутри потока:
Код:
 if terminated then exit
Но, а если в данный момент подвис idhttp? Как все это дело вырубить и завершить?
Anfall вне форума Ответить с цитированием
Старый 16.08.2011, 21:26   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
а если в данный момент подвис idhttp?
Ну дык самое ему время Terminate
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 16.08.2011, 21:33   #7
Anfall
Форумчанин
 
Регистрация: 10.02.2009
Сообщений: 181
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Ну дык самое ему время Terminate
Ну так я не понимаю, а как завершить-то его? Termiante тупо ставит terminated в true. Поэтому надо как-то завершать поток по-иному.
Anfall вне форума Ответить с цитированием
Старый 16.08.2011, 21:43   #8
mss
Заблокирован
 
Регистрация: 27.05.2010
Сообщений: 1,099
По умолчанию

Ну так закрой хендл гнезда, используемого IdHTTP-объектом, из другого потока - и всех делов)
Он тебе вернет исключение, мол, кирдык гнезду, не могу дальше рабоать - и закруглится (если правильно обработаешь исключение)

А дальше полный простор для "творчества").. хоть оно и сомнительно в разуме подающего идею на тему "хочу изнасиловать НОРМАЛЬНОЕ выполнение запроса"
mss вне форума Ответить с цитированием
Старый 17.08.2011, 08:05   #9
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Цитата:
FreeOnTerminate:=true;
конфликтует с

Цитата:
если поток уже существует, то корректно остановить его
С FreeOnTerminate в True поток может удалить в любой, в том числе и самый неподходящий, момент.

Если FreeOnTerminate = True, то вы не должны сохранять объект поток в переменную, за исключением одного весьма специализированного (и, пожалуй, извращённого) случая с передачей указателя на эту переменную для очистки в сам поток.

Цитата:
Но проблема-то в то что, а как толково завершить поток? Если б там был бы какой-то простой цикл, то можно было бы сделать:
Код:
Sometread.terminate.
А внутри потока:
Код:
if terminated then exit
Но, а если в данный момент подвис idhttp? Как все это дело вырубить и завершить?
Классически это делается так: вы делаете Terminate и тут же очищаете переменную (без удаления). Всё, можно создавать новый поток.

Т.е. вы даёте команду на останов, но не ждёте её завершения.

Поток будет работать, да. Но, ближайшее его действие - увидеть, что ему надо завершать работу. Так что он остановится и удалит свой объект (установкой FreeOnTerminate - это можно делать теперь, потому что если нам дали команду на удаление, то на поток уже не ссылается никто).

Главное тут - не напутать, когда кто удаляет.

Если поток завершается штатно, то FreeOnTerminate = False, его объект сохранён в переменной и главный поток может в любой момент проверить завершение потока, его статус, результат вычислений и использовать переменную для коммуникации с потоком. Главный поток удаляет переменную при выходе из программы, при создании нового потока (если старый уже закончил работу), но не удаляет её при остановке ещё работающего потока (между последними двумя пунктами важна синхронизация).

Если потоку дали команду на выход, то он обязан проверять этот флаг (Terminated) перед каждым важным и длительным действием. Кроме того, он обязан проверить флаг перед самым выходом. При обнаружении признака выхода он делает FreeOnTerminate := True + Abort.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 17.08.2011, 10:22   #10
Anfall
Форумчанин
 
Регистрация: 10.02.2009
Сообщений: 181
По умолчанию

GunSmoker, как всегда спасибо.
Более менее понятно уже.

А если сделать проще.
по событию:
Код:
if somethread<>nil then
  somethread.free;
somethread:=Tsomethread.Create('v1','v2');
somethread.Resume;
(при этом FreeOnTermiante=false)

А в деструторе потока написать все про удаление idhttp.
+ при выходе программы также написать
Код:
if somethread<>nil then
  somethread.free;
Чем чреват вот такой код?
Anfall вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
потоки Cpluser Общие вопросы .NET 5 15.02.2011 22:17
потоки Cpluser C# (си шарп) 0 14.02.2011 21:24
Потоки _-Re@l-_ Общие вопросы Delphi 6 18.01.2011 20:45
потоки пауэрлифтинг Общие вопросы Delphi 5 23.05.2010 14:19