Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » ошибка в уничтожении потока Delphi+Thread+TerminateThread

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2

Открыть новую тему     Написать ответ в эту тему

Delphi6



BANNED
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Хотя в конкретном моем случае речь идет о Delphi, но думаю вопрос больше общий так как касается API функции, которые одинаковые как по синтаксису так и среде использованию для всех (почти) языков. Дело касается потоков и функции TerminateThread(thread.Handle, 0);
 
Теперь немного о моей программе. В программе есть потоки которые выполняют некую работу. Допустим качают данные с какого-то сайта. Назовем его "поток скачки". Так как у скачки должен быть timeout, я "поток скачки" поместил в другой поток который следит за временем, и в случае его истечения заверещал "поток скачки" аварийно, TerminateThread("поток скачки".handle, 0); Назовем этот "поток проверки".  
 
В итоге что бы выполнить задания закачки одновременно я создавал несколько "потоков проверки" и ждал пока они все закончат работу. Результат мог быть или положительный, а значит "поток скачки" завершил работу удачно, либо отрицательный, не смогли скачать или кончилось время. После чего данный "поток проверки" убивался также функцией TerminateThread("поток проверки".handle, 0); после чего заново запускался но уже с новыми параметрами.
 
Но при тестировании и наблюдениями за поведением кода, было замечено что после того как первые 10 "потоков проверки" (а это был массив) завершал работу и запускались новые 10 потоков некоторые вообще исчезали. Другими словами есть подозрение что функция TerminateThread убивала больше одного потока за раз! Так как при подсчете, а я учитывал когда поток заканчивал работу, разница была в 50%. Толи потоки не могли быть убиты, толи наоборот их убили случайно
 
Одним словом, конечно сложно что-то советовать прочитав выше указанный алгоритм, но может у вас была похожая ситуация? И вообще как можно завершить работу потока аварийно. Что бы наглухо, так как алгоритм Thread.Teriminate не подходит, он завершает работу только после того как внутренние компоненты (созданные в потоке) завершат работу.
 
Заранее благодарю всех сначала за время потраченное на прочтение такого большого текста и потом за ответ
 
Добавлено:
Сори но кажеться я сам лично нашел ошибку, досканально проверял каждый компонент по отдельности и кажеться ошибка вообше банальная (в чужом компоненте не доработка )

Всего записей: 2631 | Зарегистр. 06-07-2004 | Отправлено: 06:12 31-05-2006 | Исправлено: Delphi6, 06:29 31-05-2006
FireZone

Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Delphi6
Будь очень внимательным к освобождению ресурсов при использовании TerminateThread. Например, если у тебя Thread.FreeOnTerminate установлено в истину, то автоматического уничтожения объекта Thread у тебя не произойдет при использовании TerminateThread. Метод Thread.Terminate предназначен для установки в истину поля Thread.Terminated, и в пользовательском методе Thread.Execute полезно проверять это поле (если в потоке используется цикл) и покидать цикл, чтобы метод Thread.Execute нормально завершился. Кроме того, если ты используешь в потоке блоки try-finally-end, то нет никакой гарантии, что блок finally у тебя выполнится при прерывании потока через TerminateThread, и, например, выделенная тобой в потоке память останется потерянной.

Всего записей: 293 | Зарегистр. 28-01-2004 | Отправлено: 11:04 31-05-2006
Anatoliy_A

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
>> И вообще как можно завершить работу потока аварийно.
 
Thread.Suspend;
Thread.Free;

Всего записей: 27 | Зарегистр. 29-04-2004 | Отправлено: 11:26 31-05-2006
dyr farot

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
все ресурсы в рабочем потоке выделяй только как члены класса -- тогда при уничтожении объекта они не потеряются.
к тому же непонятно зачем каждому рабочемы потоку выделять по потоку-надсмоторщику. достаточно и одного потока на всех

Всего записей: 697 | Зарегистр. 03-08-2004 | Отправлено: 12:26 31-05-2006
OdesitVadim



Advanced Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Anatoliy_A

Цитата:
>> И вообще как можно завершить работу потока аварийно.  
 
Thread.Suspend;  
Thread.Free;

Но стрёмно, поток может не завершиться так как надо.
Лучше сделать, так как сделали в одном сетевом сканере - создают ещё одно маленькое приложение и запускают несколько копий. Все проблемы быстро решаются

----------
Press any key to continue or any other key to exit
Пишите так, чтобы не было стыдно за нобелевскую премию.

Всего записей: 1568 | Зарегистр. 19-09-2003 | Отправлено: 12:43 31-05-2006
Mickey_from_nsk

Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Delphi6
Вообще, в умных книгах (например, в Рихтере) пишут, что такая методика (TerminateThread) не есть очень хорошо.  
Может пересмотреть механизм скачки? Например, в самом потоке сделать таймаут, или по таймауту закрывать сокет? Это будет (я так думаю) более удачным решением. В этом случае сам поток поймет, что надо закрываться и грамотно освободит свои ресурсы.

Всего записей: 636 | Зарегистр. 21-10-2002 | Отправлено: 13:56 31-05-2006
Delphi6



BANNED
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
Thread.Suspend;
Thread.Free;

это и есть то что я говорю нереально. Допустим у меня была в прошлом такая ситуация когда информация считывалась с носителя CD. Так вот если место где происходило считывание было повреждено, то даже по истечении времени команда suspend не работала, поток уничтожался только после того как истекало время считывания данных (системный таимаут) и генерировалась ошибка (ее конечно отлавливал), И что я имел в результате, 30 секунд ждал пока поток завершит работу.
Когда функция TerminateThread убивает поток насмерть мгновенно! Вот только не знаю насколько качественно освобождается потом память при вызове команды thread.free, хотя думаю память должна освобождаться Думаю это легко проверить если запустить и уничтожить до 10.000 потоков.
 

Цитата:
Лучше сделать, так как сделали в одном сетевом сканере - создают ещё одно маленькое приложение и запускают несколько копий. Все проблемы быстро решаются

идейка хорошая, но как потом результат работы каждой программки получать? В файл кидать и потом считывать? но все это доп. ресурсы, учитывая что все на дельфи пишется, хотя если будет не визуальная программулька то думаю все будет ок. Мой вердикт, для моих целей слишком наворочена, да и так работает без проблем пока.
 

Цитата:
все ресурсы в рабочем потоке выделяй только как члены класса

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

Цитата:
то автоматического уничтожения объекта Thread у тебя не произойдет

для этой цели я на всякий случай после это команды вызываю thread.free что как я думаю должно освобождать память.
 

Цитата:
Рихтере

Это есть зло, он даже писал что надо делать синхронизацию а это оказалось самой большой ошибкой, читал на этот счет много статей в интернете Так что кто знает
 

Цитата:
достаточно и одного потока на всех

ок если вы внимательно прочтете алгоритм то заметите что есть вероятность что код закачки в "потоке закачки" может повиснуть, а именно закачка может длиться очень долго если скорость соединения очень мала, а как вы собираетесь после таимаута его убить? Только запустив в потоке и контролируя пройденное время снаружи.
Зачем второй поток? А как вы собираетесь контролировать сразу несколько запушенных закачек? Не легче все это оформить в виде одного потока который сам будет следить за всем и через таимаут время выдаст результат или положительный или отрицательный. Сам проанализирует результаты работы "потока закачки". Вам же остается просто запустить 10 (к слову) "потоков проверки" и ждать когда же они все закончат работу (а они сто пудово закончат работу вовремя).
 
Ну думаю один очень мудрый совет получил на счет того что "поток закачки" лучше оформить в виде члена класса "поток проверки".
 
И что TerminateThread есть зло. Я согласен, даже читал один мануал в котором говорилось не о TermiateThread а что-то вроде SuspendThread который точно зло, так как в примере было показано как программу можно подвесить такой функцией случайно.
 
Вопрос до сих пор актуален, как вы убиваете поток, в котором не просто бесконечный цикл (на него команда suspend) сработает, а компонент который работает с внешним миром, типа считывает данные с носителей, качает данные из инета, или проверяет содержимое другой программы или еще что.
 
Добавлено:

Цитата:
Может пересмотреть механизм скачки? Например, в самом потоке сделать таймаут, или по таймауту закрывать сокет? Это будет (я так думаю) более удачным решением. В этом случае сам поток поймет, что надо закрываться и грамотно освободит свои ресурсы.

А как можно остановить закачку, допустим компонента TIdHTTP? Я думаю это не реально, хотя возможно есть способ, сейчас пробью в инете...
 
Добавлено:
Вот в соседнем форуме ведеться обсуждение и вот что один сказал

Цитата:
При работе с сокетами (сетью), к сожалению, нормального способа быстро уничтожить поток нет. Если сокет ждет подключения (ответа сервера), сервер не отвечает, поток можно будет убить только после возникновения таймаута. Многие известные программы (в том числе и от MS) уничтожают потоки аварийно, а потом как-то подчищают ресурсы.

http://delphimaster.ru/cgi-bin/forum.pl?id=1149041613&n=5

Всего записей: 2631 | Зарегистр. 06-07-2004 | Отправлено: 17:13 31-05-2006
OdesitVadim



Advanced Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Delphi6

Цитата:
то автоматического уничтожения объекта Thread у тебя не произойдет     
 
для этой цели я на всякий случай после это команды вызываю thread.free что как я думаю должно освобождать память.

Будут подчищены только VCL ресурсы. А ведь ещё есть и Windows'овские. И неизвесно, как поведёт себя класс TThread при попытке удалить ресурсы, наличие которых под вопросом (поток мы прибили, а ресурсы потока ушли в свободное плаванье)

----------
Press any key to continue or any other key to exit
Пишите так, чтобы не было стыдно за нобелевскую премию.

Всего записей: 1568 | Зарегистр. 19-09-2003 | Отправлено: 17:36 31-05-2006
Delphi6



BANNED
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
OdesitVadim
Ок, тепер ясно куда капать надо. А как можно подчистить все. Получаеться если я пользуюсь IdHTTP то надо перед уничтожением потока сделать IdHTTP.Free?

Всего записей: 2631 | Зарегистр. 06-07-2004 | Отправлено: 17:42 31-05-2006
vserd

Silver Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Delphi6

Цитата:
Когда функция TerminateThread убивает поток насмерть мгновенно! Вот только не знаю насколько качественно освобождается потом память при вызове команды thread.free,

Такой текст из справки по WIN32 API устроит?
 
TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:
 
·    If the target thread owns a critical section, the critical section will not be released.  
·    If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.  
·    If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.
 
 
 
A thread cannot protect itself against TerminateThread, other than by controlling access to its handles. The thread handle returned by the CreateThread and CreateProcess functions has THREAD_TERMINATE access, so any caller holding one of these handles can terminate your thread.
If the target thread is the last thread of a process when this function is called, the thread's process is also terminated.  
The state of the thread object becomes signaled, releasing any other threads that had been waiting for the thread to terminate. The thread's termination status changes from STILL_ACTIVE to the value of the dwExitCode parameter.  
 
Terminating a thread does not necessarily remove the thread object from the system. A thread object is deleted when the last thread handle is closed.

Всего записей: 2065 | Зарегистр. 08-05-2002 | Отправлено: 18:19 31-05-2006
OdesitVadim



Advanced Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Delphi6

Цитата:
Ок, тепер ясно куда капать надо. А как можно подчистить все. Получаеться если я пользуюсь IdHTTP то надо перед уничтожением потока сделать IdHTTP.Free?

Даже не знаю. А если поток в это время работает с компонентом? Не будет ли аксес виолейшенов? Поток обратиться к несуществующему компоненту. К тому же синхронизация необходима при доступе к компоненту. А там может быть проблема с критическими секциями. Поток вошёл в неё и не вышел. Основной поток не может обратиться к нему.
Я не знаю, как у Вас там организовано, но думаю, что с удалением будут бяки. И лучшим на мой взгляд есть создание дополнительной программы, которой оттдаются указания.

----------
Press any key to continue or any other key to exit
Пишите так, чтобы не было стыдно за нобелевскую премию.

Всего записей: 1568 | Зарегистр. 19-09-2003 | Отправлено: 19:31 31-05-2006
FireZone

Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Delphi6
Мне тут идейка пришла... Из контролирующего потока попробуй сделать closesocket своему IdHTTP, тогда процесс соединения отвалится и поток нормально завершится. Для этого, видимо, при создании экземпляра IdHTTP тебе нужно "положить куда-нибудь на видное место" хэндл лежащего в его основе сокета.

Всего записей: 293 | Зарегистр. 28-01-2004 | Отправлено: 19:43 31-05-2006
Delphi6



BANNED
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
OdesitVadim
Что вы подразумеваете когда говорите что поток может обращаться к не существующему компоненту? Единственный компонент с которым он работает, создается в нем же самом. Получается если поток умирает то и компонент сдыхает. Или я не совсем правильно представляю что есть поток?
 
FireZone
Самая мудрая идея, вот это я и хочу проверить, на другом форуме говорили что именно так можно прикрыть соединение аварийно. Посмотрим как на практике.
 
vserd
Спасибо за выписку из доки.
 
Все больше и больше я начинаю понимать что есть вероятность потери/утечки ресурсов.
 
Добавлено:
Думаю теперь все грамотно?
 
Thread.TerminateConnection;
Thread.Terminate;
Thread.Free;
 
procedure TMyThread.TerminateConnection;
begin
  fIdHTTP.DisconnectSocket;
  fIdHTTP.Free;
end;
 
Что скажете теперь знатоки? Проблем и ошибок не было, код работает как часики, если мне не показалось то он работает намного быстрей Чем с конструкцией TerminateThread

Всего записей: 2631 | Зарегистр. 06-07-2004 | Отправлено: 02:18 01-06-2006
Delphi6



BANNED
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Как и можно было ожидать, где-то просочилась ошибка Хоть поток удаляется по всем правилам, где-то генерируется ошибка и прога автоматом, без сообщений об ошибке вырубается Когда и при каких обстоятельствах пока не известно, но где-то после 200 запуска/уничтожения потока (прогу оставил работать, сам пошел чаек попить).
Сейчас добавлю в программу ведения логов и буду ловить ошибку. А как можно отловить все ошибки возникшие при работе программы? Что бы хотя бы понять где приблизительно ошибка
 
Добавлено:
Лог файлы показали что, после 500 запусков и уничтожений остаются потоки которые не могут быть завершены! А именно мое подозрение касающийся fIdHTTP.DisconnectSocket не срабатывает и поток продолжает работать. Сейчас думаю есть смысл проверить что будет с TerminateThread и запуском 500 раз? Если ошибок не будет то мое подозрение подтвердиться фактом
 
Добавлено:
Тестирование с функцией TerminateThread
 
Начну с самого лавного, утечка в памяти есть. Не все ресурсы высвобождаются, хотя зато все работает как часы. Потеря не велика до 1мб при запуске/уничтожении 1000 потоков. Сначала было больше пока я не добавил строку IdHTTP.Free до уничтожения потока.
 
Теперь возникает логический вопрос, как все же убить поток удачно, или что еще надо зачистить? Кроме IdHTTP поток не использует ничего кроме переменных. Не думаю что именно они и не освобождаются И как можно системе передать сообщение что типа убей поток и подчисти все, или дядя Бил это не предусмотрел? И по этой причине винда часто летит?

Всего записей: 2631 | Зарегистр. 06-07-2004 | Отправлено: 09:13 01-06-2006
FireZone

Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Delphi6
ИМХО, лучше сделать так:
Код:
 
procedure TMyThread.TerminateConnection;  
begin  
  // Вызываем DisconnectSocket только если fIdHTTP существует (не равен nil)
  if Assigned(fIdHTTP) then fIdHTTP.DisconnectSocket  
end;
 
procedure TMyThread.Execute;  
begin
  try
    fIdHTTP := TIdHTTP.Create(nil); //создаём экземпляр TIdHTTP
    try
      ...
      fIdHTTP.Connect; // Это тот самый коннект, на котором происходит зависание
      ...
    finally
      FreeAndNil(fIdHTTP) //уничтожаем экземпляр
    end
  except
    on E: Exception do AddToLogFile(E.ClassName + ': ' + E.Message);//Пишем в лог возникшие исключения
    //Если был вызван DisconnectSocket, то метод Connect должен выскочить с исключением
  end
end;
Если не использовать TerminateThread, то при таком подходе экземпляр TIdHTTP будет правильно уничтожен. Для большей надёжности можно ввести проверку "а коннект ли сейчас отрабатывается?"
 
Добавлено:
Delphi6
Цитата:
Thread.TerminateConnection;  
Thread.Terminate;  
Thread.Free;

Если ты в потоке не проверяешь флажок Thread.Terminated, который говорит потоку о том, что его хотят завершить, то Thread.Terminate здесь совершенно бесполезное действие.
Было б неплохо с твоей стороны привести код, чтобы можно было общими усилиями поискать в нём грабли. Ресурсы просто так никуда не теряются.

Всего записей: 293 | Зарегистр. 28-01-2004 | Отправлено: 11:16 01-06-2006
OdesitVadim



Advanced Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Delphi6

Цитата:
 Получается если поток умирает то и компонент сдыхает. Или я не совсем правильно представляю что есть поток?

Если поток умирает "цивилизованым способом", то его VCL обёртка по всем правилам удаляет дочерние компоненты. Если же его убивают жёстко, то он не в состоянии это отследить.
 
Эксперементы - это правильно! Побольше их.

----------
Press any key to continue or any other key to exit
Пишите так, чтобы не было стыдно за нобелевскую премию.

Всего записей: 1568 | Зарегистр. 19-09-2003 | Отправлено: 12:08 01-06-2006
Delphi6



BANNED
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Сори что долго не отвечал, был в out-е
Вот код который я имею на данный момент, как можно догадаться он для проверки работаспособности прокси:

Код:
 
unit Kernel;
 
interface
 
uses
  Classes, IdHTTP, Windows, Functions, Dialogs;
 
type
  TProxyType = (ptUnknown, ptBad, ptTransparent, ptAnonymouse, ptElite, ptElitePlus);  
 
  TProxyCheckerThread = class(TThread)
  private
    fIdHTTP: TIdHTTP;
    fUrl: String;
    fCheckString: String;
    fResult: Boolean;
    fResultString: String;
  protected
  public
    constructor Create(Url, Server: String; Port: Integer); overload;
    procedure Execute; override;
         
    procedure TerminateConnection();
    function GetResult: Boolean;
    function GetResultString: String;
  end;
 
  TProxyChecker = class(TThread)
  private
    fUrl: String;
    fCheckString: String;
    fServer: String;
    fPort: Integer;
    fTimeout: Integer;
    fResult: Boolean;
 
    //Result variables
    fProxyType: TProxyType;
    fProxyLatency: Integer;
    fProxySSLSupport: Boolean;
    fProxyCountryCode: String;
    fProxyCountryName: String;
  protected
    ...удалено для облегчения кода...
  public
    constructor Create(Url, CheckString, Server: String;
      Port, Timeout: Integer); overload;
    procedure Execute; override;
 
    function GetResult: Boolean;
    function GetProxyType: TProxyType;
    function GetLatancy: Integer;
  end;
 
implementation
 
//======================================================
//TProxyCheckerThread BEGIN
//======================================================
 
constructor TProxyCheckerThread.Create(Url, Server: String; Port: Integer);
begin
  //Create thread in suspending mode
  inherited Create(True);
 
  fResult := false;
  fResultString := '';
  //Create TIdHTTP component to retrive information
  fIdHTTP := TIdHTTP.Create(nil);
  fIdHTTP.Request.ProxyServer := Server;
  fIdHTTP.Request.ProxyPort := Port;
  fUrl := Url;
  Resume;
end;
 
procedure TProxyCheckerThread.Execute;
begin
  try
    fResultString := fIdHTTP.Get(fUrl);
  except
    //Error in connection
    exit;
  end;
  fResult := True;
end;
 
procedure TProxyCheckerThread.TerminateConnection;
begin
  if Assigned(fIdHTTP) then begin
    fIdHTTP.DisconnectSocket;
    fIdHTTP.Free;
  end;
end;
 
...удалено для облегчения кода...
 
//======================================================
//TProxyCheckerThread END
//======================================================
 
 
 
//======================================================
//TProxyChecker BEGIN
//======================================================
 
constructor TProxyChecker.Create(Url, CheckString, Server: String;
  Port, Timeout: Integer);
begin
  //Create thread in suspending mode
  inherited Create(True);
  //Set thread's settings and execute it
  //Priority := tpIdle;
  fUrl := Url;
  fCheckString := CheckString;
  fServer := Server;
  fPort := Port;
  fTimeout := Timeout;
  //Prepare global variables
  fResult := false;
  fProxyType := ptBad;
  Resume;
end;
 
procedure TProxyChecker.Execute;
  var
    PCT: TProxyCheckerThread;
    StartTime: Integer;
    timePass: Integer;
begin
  //Prepare thread and execute to recieve result from URL
  PCT := TProxyCheckerThread.Create(fUrl, fServer, fPort);
  StartTime := GetTickCount;
  timePass := 0;
  //Work until time will finish and result from page will be recieved
  while (timePass < fTimeout) and (not PCT.GetResult) do begin
    timePass := GetTickCount-StartTime;
    //Wait for result or timeout
  end;
  //Checking if result exist and analyze it
  if PCT.GetResult then begin
    fProxyLatency := timePass;
    AnalyzeResult(PCT.GetResultString);
  end else
    fProxyType := ptBad;
  //Remove thread, even in case if it still running
  //First of all of cause terminate any connection
  PCT.TerminateConnection;
  PCT.WaitFor;
  PCT.Free;
  fResult := True;
end;
 
...удалено для облегчения кода...
 
//======================================================
//TProxyChecker END
//======================================================
end.
 

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

Всего записей: 2631 | Зарегистр. 06-07-2004 | Отправлено: 03:12 02-06-2006 | Исправлено: Delphi6, 04:53 02-06-2006
ShIvADeSt



Moderator
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
procedure TProxyCheckerThread.TerminateConnection;  
begin  
  if Assigned(fIdHTTP) then begin  
    fIdHTTP.DisconnectSocket;  
    fIdHTTP.Free;  
  end;  
end;

Попробуй fIdHTTP.FreeAndNil скорее всего не обнуляет. В каком то топике что то аналогичное рассматривалось.

----------
И создал Бог женщину... Существо получилось злобное, но забавное...

Всего записей: 3956 | Зарегистр. 29-07-2003 | Отправлено: 06:32 02-06-2006
Delphi6



BANNED
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
Попробуй fIdHTTP.FreeAndNil скорее всего не обнуляет. В каком то топике что то аналогичное рассматривалось.

Вместо обеих строк или все же надо делать DisconectSocket?

Всего записей: 2631 | Зарегистр. 06-07-2004 | Отправлено: 07:27 02-06-2006 | Исправлено: Delphi6, 07:27 02-06-2006
FireZone

Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Delphi6
Если ты fIdHTTP создаёшь в конструкторе своего потокового объекта, то уничтожать его лучше в деструкторе, а TerminateConnection использовать только для разрыва соединения. Тут возможны грабли: если к моменту вызова DisconnectSocket соединение было разорвано к примеру сервером, или вообще не было установлено, то должно вылететь исключение и до fIdHTTP.Free дело не дойдёт. В этом случае, при уничтожении потокового объекта твой fIdHTTP останется болтаться в памяти до завершения приложения. Насчёт исключения надо глянуть исходники Indy; не уверен, что оно там есть, но возможно. Чтобы хоть что-то попробовать отследить, сделай кое-какие изменения:
Код:
 
procedure TProxyCheckerThread.TerminateConnection;  
begin  
  if Assigned(fIdHTTP) then begin  
    try
      fIdHTTP.DisconnectSocket;  
      FreeAndNil(fIdHTTP) //Функция вызывает метод Free и затем обнуляет указатель fIdHTTP,  
      //чтобы следующая проверка Assigned(fIdHTTP) дала ложь.
    except
      //Пишем в лог все исключения
      on E: Exception do begin
        AddToLogfile('ошибка в TerminateConnection: '+E.ClassName + ': ' + E.Message);
        raise //Заново возбуждаем исключение, чтобы не изменить ход выполнения
      end
    end
  end;  
end;  
 
procedure TProxyCheckerThread.Execute;  
begin  
  try  
    fResultString := fIdHTTP.Get(fUrl);  
  except  
    //Error in connection  
      //Пишем в лог все исключения
      on E: Exception do begin
        AddToLogfile('ошибка в TProxyCheckerThread.Execute: '+E.ClassName + ': ' + E.Message);
        Exit
      end
  end;  
  fResult := True;  
end;
 

Всего записей: 293 | Зарегистр. 28-01-2004 | Отправлено: 08:27 02-06-2006
Открыть новую тему     Написать ответ в эту тему

Страницы: 1 2

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » ошибка в уничтожении потока Delphi+Thread+TerminateThread


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2025

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru