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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 28.11.2011, 13:44   #11
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Можно сделать и так, как предложено в предыдущем посте, добавив в Destroy передачу сообщения окну для сигнала о том, что поток завершен. При получении этого сообщения окно новый поток будет создавать, возможно сделав небольшую паузу.

Можно и оставить так как есть, пересмотрев кое-что

1. inherited в Execute не понятно для чего (уже говорилось)
2. Если извне сделать Terminated:=True, то все объекты созданные в Execute могут быть и не уничтожены, поскольку уничтожение внутри цикла, куда прога может и не войти, плюс Exit-ы есть в цикле до уничтожения. Если извне не предусмотрена установка Terminated в True, то нафиг все эти проверки внутри Execute этого свойства? Создание и удаление объектов конечно лучше перенести в Create и Destroy
3. У вас синхронный способ создания потоков и для создания его по-новой окно должно дождаться завершения предыдущего экземпляра. А ваше Stop похоже вызывается из потока через fOnTimeout, прикольно. Используйте метод WaitFor в окне для ожидания завершения потока и только после его выполнения уничтожайте поток. Инициализировать процедуру ожидания завершения потока и его уничтожения можно, например, передав сообщение из потока в окно перед самым выходом из Execute.
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию

Последний раз редактировалось Аватар; 28.11.2011 в 13:47.
Аватар вне форума Ответить с цитированием
Старый 28.11.2011, 15:27   #12
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Это ты пинг делаешь для Контры как я понял)? У меня есть для контры кое что написано под WinSock сразу можно многопоточность создать, есть опрос мастер серверов, есть прога для управления rcon командами для удаленной консоли, если хочешь могу поделиться, может кое что полезного найдешь и там все на потоках построено
Aliens_wolfs вне форума Ответить с цитированием
Старый 28.11.2011, 16:00   #13
xrob
Форумчанин
 
Регистрация: 18.10.2010
Сообщений: 419
По умолчанию

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

Я(я) запускаю поток, который выполняет это действие.
Т(т)аймер со стороны по истечении времени просто прерывает этот поток.

П(п)рерывает с помощью TerminateThread.
Э(э)то жуткая функция, которой все боя(ца)ТСЯ, и применение которой, как я слышал, в корне неправильно, но поток убивает на раз, без всяких тупых вопросов.
П(п)росто почитайте возможные опасности, связанные с ней, и решите, надо ли оно вам.
Л(л)ично я использую и доволен =)

О(о)дна из опасностей, которых все боя(ца)ТСЯ - это неосвобождение памяти после убиения потока.
М(м)ол, если убить поток просто так, то он не освобождает объекты, которые создавал.
Н(н)о лично я, например не представляю как надо написать программу, чтобы поток там что-то создавал...
Я(я) все что надо создаю просто так, а поток уже потом с этим работает...

Из правил раздела :
6. У нас принято писать грамотно, нормальным русским языком, с использованием знаков препинания и заглавных букв в начале предложений. "Каша" или "удафф" будут тут же закрыты с выдачей штрафа.
Так что, если у вас проблемы с этим, проверяйте свои сообщения на орфографию в Ворде или браузере...
Модераторы это дело подправят, а вы получите штраф...

Последний раз редактировалось mihali4; 29.11.2011 в 19:19.
xrob вне форума Ответить с цитированием
Старый 28.11.2011, 17:36   #14
3D Hunter
Сумрачная тень
Форумчанин
 
Аватар для 3D Hunter
 
Регистрация: 05.03.2009
Сообщений: 689
По умолчанию

Прочитал все посты, посмотрел код... Скажу вот что: Автор темы, вам следует начать решать проблему не в коде, а в самой концепции. Итак, по порядку:
1. Таймер проверяет, существует ли поток и при необходимости пересоздает поток... Зачем? Убирайте таймер, и перепишите код потока так, чтобы он создавался при старте вашей программы и занимался пропинговкой нужного сервиса на протяжении всей работы программы. Если коннект оборвался или UDP-сообщение не доставлено, то не нужно уничтожать поток! Организуйте цикл Execute так, чтобы в цикле происходил реконнект и пропинговка возобновлялась.

2. Раз в секунду? В цикле потока код:
Код:
Sleep(1000);
3. Ваш код создания потока требует переопределения конструктора для него, например так:
Код:
constructor TPingThread.Create;
begin
  Inherited Create(True);
  Timeout := AppInfo.ServerPingTimeout;
  IP := AppInfo.ServerIP;
  Port := AppInfo.ServerPort;
  FreeOnTerminate := True;
  Priority := tpHigher;
  OnTimeout := OnPingTimeout;
  Resume;//или Start; - если Delphi 2010 или XE
end;
Это замена кода в таймере.

4. TPingThread.SetProc может не выполнять код в finally после вызова Exit, если опять-таки, версия Delphi, кажется, ниже 2009. Т.е. Exit не кидает в finally. Если так, то обезопасьте дополнительной оберткой try..except весь код данного метода и замените Exit на Abort. А лучше строки кода по освобождению объектов вынести в деструктор.

5. Грубая ошибка в вашем коде:
Код:
procedure Stop;
begin
      if not (PingThr = nil) then
      begin
        FreeAndNil(PingThr); //программа вешается 
      end;
end;
А с чего бы она не вешалась, если поток выполняется и не перешел в спящее состояние? Тогда уж освобождайте поток при FreeOnTerminate=false так:
Код:
  PingThr.Terminate;
  PingThr.WaitFor;
  FreeAndNil(PingThr);
Вы пренебрегаете классами, стараясь использовать возможности компонентов и встроенных классов VCL. Как я сказал, лучше полностью переписать класс потока с конструктором и деструктором, с полным самоконтролем разрыва связи и ее восстановления. Тогда и таймер не понадобится, и проверки на nil не будут. Если очень хотите пересоздавать поток, то в деструкторе потока и создавайте новую копию потока, присваивая его вашей глобальной переменной. Только учтите проверку на выключение программы, т.е. когда поток будет уничтожаться, чтобы он проверял, а нужно ли создавать себя снова. Поможет глобальная логическая переменная. Но это не самый удачный метод. В общем, классы и еще раз классы. Вся логика в них, и тогда ваш код будет самодостаточен в локальных зонах.

Отдельно для xrob
Вам, уважаемый, лучше не писать такие изречения, дабы не позориться. Без обид. Набирайтесь опыта, книги читайте и блоги листайте. WinApi вещь отличная, только ей нужно уметь пользоваться.
"ковыряю изнутри" (с)

Последний раз редактировалось 3D Hunter; 28.11.2011 в 18:19.
3D Hunter вне форума Ответить с цитированием
Старый 28.11.2011, 19:49   #15
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

3D Hunter, таймер выкинул. Написал конструктор и деструктор.
Только не понял как реализовать reconnect при обрыве связи.

Делее понял проблему.
в fOnTimeOut у меня выставлен обработчик такого вида:
Код:
procedure OnPingTimeout;
begin
  Restart;
end;
Код:
procedure Restart;
begin
  Stop;
  Start;
end;
Получается, что поток сам себя пытается прихлопнуть. Оттого при вызове WaitFor или Free вешает всю программу.
Как этого избежать?
Человек_Борща вне форума Ответить с цитированием
Старый 28.11.2011, 19:56   #16
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

OnPingTimeout и не нужен. Сообщение отправляйте перед выходом из Execute, а в обработчике сообщения WaitFor, Free и создание нового потока
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 28.11.2011, 20:49   #17
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Сделай дополнительный класс который будет проверять уничтожение потока, потом через него заново запускай создавая новый поток. Этот же класс и позволит создавать многопоточность отслеживая все потоки.
Один раз создаешь класс по работе с потоком потом он сам будет создавать и уничтожать поток в свой TList он в этот лист вернее в память грузит параметры потоков, с помощью его можешь узнать количество запущенных или узнать уничтожен ли поток по его индексу в листе или идентификатору по спец номеру который задашь потоку. Просмотри ниже прогу, разберешься.
Я благодаря ВОВАНУ разобрался с потоками, видел его примеры на них и научился контролировать потоки.
Или поищи примеры от ВОВАНА особенно по написанию Mail агента, у него там много чего интересного.

http://zalil.ru/32152725 прога для КС опрашивает мастер сервер из списка и выдает сервера в этом сервере. Там в FunctConnect.pas и реализованны все функции потоков по сети, просмотри код и разберешся как приструнить поток)

при запуске проги нажми в ней кнопку Загрузить список и ты увидешь в ListView всю инфу о серверах КС которые зарегистрированны на мастер сервере. много чего полезного там есть.

Последний раз редактировалось Aliens_wolfs; 28.11.2011 в 21:23.
Aliens_wolfs вне форума Ответить с цитированием
Старый 28.11.2011, 20:58   #18
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

эмм,
Цитата:
Сообщение отправляйте перед выходом из Execute, а в обработчике сообщения WaitFor
Сообщение куда? Там класс, не привязанный к форме.
А про обработчик WaitFor впервые слышу...

Можно просвятить?
Человек_Борща вне форума Ответить с цитированием
Старый 28.11.2011, 21:25   #19
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Ну во-первых вроде и нет упоминания, что у вас окна нет, которому можно сообщение передать, во вторых обработчика WaitFor нет, а имелся ввиду обработчик сообщения, в котором выполняеься WaitFor, Free и создание нового потока. Все равно у вас есть поток, из которого запускается пингующий поток. Ставьте сразу после запуска пингующего потока ожидание его завершения, тогда никаких сообщений не нужно
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию

Последний раз редактировалось Аватар; 28.11.2011 в 21:39.
Аватар вне форума Ответить с цитированием
Старый 29.11.2011, 05:15   #20
3D Hunter
Сумрачная тень
Форумчанин
 
Аватар для 3D Hunter
 
Регистрация: 05.03.2009
Сообщений: 689
По умолчанию

Вы правильно сказали: объект не может уничтожить сам себя непосредственно, т.к. в этом случае он делает это из своего метода. А после выполнения строчки FreeAndNill() идет возврат в точку вызова для продолжения исполнения линейного кода и... упс! А там-то уже ничего по этому адресу и нет!

Создавать поток только для ожидания завершения другого крайне нерационально. Лучше уж тогда определить событие OnTerminate вашего проблемного потока, и в нем написать код для запуска новой копии потока. Тогда вам не нужно будет заботиться о самопроверке "уничтожен ли я?", а старый поток будет корректно освобождаться в своем деструкторе. Кроме того, получается, что он же и будет контролировать сам себя, говоря лишь в OnTerminate главному потоку приложения создать новую копию себя.

По коду:
1. Вынесите процедуру Start в событие OnTerminate. В конструкторе потока установить FreeOnTerminate:=true для самоконтроля.

2. В деструкторе должен выполняться код по освобождению объектов:
Код:
destructor TPingThread.Destroy;
begin
  FreeAndNil(UDP);
  CloseHandle(Event);
  Inherited Destroy;
end;
3. В событии OnTerminate создавать новую копию примерно так:
Код:
procedure TPingThread.OnTerminateProc (Sender: TObject);//этот метод выполняет не поток, а само приложение, так что безопасно
begin
  PingThr:=TPingThread.Create;//из моего предыдущего поста
end;
P.S. А вообще если возникают такие проверки, то что-то уже не так. Как правило, для множества классов-потоков должен быть класс-обертка со всеми необходимыми методами контроля и управления. Через методы такой обертки и уничтожаются потоки, например. Только здесь важно, чтобы все операции обертки выполнял либо главный поток, либо специально созданный. Но лучше главыйн поток приложения. Пусть в нем объявлена переменная класса-обертки. Через методы этого класса и создавайте потки. Этот абзац к теме мало относится, просто немного теории. Старайтесь строить иерархию с логичными и незапутанными взаимосвязями "многие-к-одному" и не допускайте уничтожение классов из их методов.

Вот почитайте эту отличную статью про многопоточность:
http://forum.vingrad.ru/forum/s/a0e9...y480344/0.html
"ковыряю изнутри" (с)

Последний раз редактировалось 3D Hunter; 29.11.2011 в 05:39.
3D Hunter вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
при закрытии потока(Tthread) посылать на форму код ответа или сообщение Человек_Борща Общие вопросы Delphi 2 14.12.2010 21:19
Работа с TThread pesi Общие вопросы Delphi 2 09.08.2010 14:12
TThread Vladislav_I Общие вопросы Delphi 0 30.04.2010 19:47
Ошибка при OpenDialog.Execute ymka2 Общие вопросы Delphi 10 27.11.2009 14:15
TThread и GUI Freezer Общие вопросы Delphi 8 05.08.2009 11:50