FreeAndNil — Процедура Delphi


Что предпочтительнее: Free или FreeAndNil?

41 Bharat [2010-07-01 18:43:00]

В чем основное отличие Free и FreeAndNil?

Is FreeAndNil = Free + Nil?

Когда я должен использовать Free и когда я должен использовать FreeAndNil?

Я не получаю их, когда кто-то может мне помочь.

5 ответов

И посмотрите на реализацию:

Примеры

Рассмотрим следующий код:

Это создаст ошибку или недопустимое (пустое) растровое изображение на моем рабочем столе, потому что я пытаюсь использовать освобожденный объект. Да, даже если bm был освобожден, он по-прежнему «назначен», т.е. bm все еще указывает на адрес памяти, хотя там нет ничего (полезного). Чтобы преодолеть это, можно установить bm := nil , как гарантию, Затем assigned(bm) вернет false, как хотелось бы. Более или менее, FreeAndNil(bm) является сокращением для bm.Free; bm := nil . Первый оператор освобождает всю память (и ресурсы ОС, время процессора и т.д., Используемые объектом), и bm := nil устанавливает «указатель» bm на nil , так что bm больше не указывает на место, где объект был, но больше не существует. Таким образом, вы (и подпрограммы вроде assigned ) не обманетесь, чтобы поверить, что все еще есть объект растрового изображения.

Обсуждение

Некоторые говорят, что вы всегда должны использовать FreeAndNil(foo) , а не foo.Free . А почему бы не? Дополнительная инструкция foo := nil , вероятно, не займет слишком много наносекунд для выполнения, и действительно assigned(foo) = false является очень приятным свойством освобожденного объекта. Но опять же, если вы знаете, что делаете, и знаете, что вы никогда не будете использовать объект foo снова, освободив его, тогда вы можете придерживаться только foo.Free . Действительно, некоторые утверждают, что во многих случаях (но не для всех) попытка использовать переменную освобожденного объекта является ошибкой сама по себе. (Конечно, есть случаи, когда вы делаете это намеренно — у вас есть объект foo , который иногда назначается, а иногда и нет.)

В принципе, FreeAndNil устанавливает ссылку на nil, а затем освобождает объект. Это означает, что он не назначен. Поэтому единственной причиной, по которой вам понадобится использовать FreeAndNil, является то, что ваш код будет повторно использовать ссылку. Если вы находитесь в деструкторе или блоке finally, освобождая объекты, которые вы никогда не будете трогать, просто используйте Free.

См. Delphi Memory Management Made Simple для примера, когда я нашел это полезным. Комментарий Mghie внизу также стоит прочитать.

Я отвечу по-другому.

Возможно, заполнение вашей ссылки на объект с помощью nil после освобождения объекта не всегда является хорошей идеей.

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

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

6 RRUZ [2010-07-01 18:57:00]

@Bharat, разница между Free и FreeAndNil заключается в том, что помимо свободной памяти, используемой объектом FreeAndNil , устанавливается ссылка на объект на nil.

вы можете проверить тезисы ссылок для обсуждения использования Free или FreeAndNil

2 Alaun [2010-12-18 01:35:00]

Даже если это не так сильно отличается от Free, это поможет вам намного позже, охотясь за ошибками вашего кода.

Подумайте, что произойдет, если вы НЕ используете FreeAndNil, а затем где-то в вашем коде вы получаете доступ к свободному объекту. Если вам повезет, ваша программа выйдет из строя, когда она вернется домой (да, это крушение — «хороший» крушение). Если вам немного не повезло, он потерпит крах на клиентском компьютере. Тогда начинается настоящая боль!

Как уже указывали другие, сам FreeAndNil неплох. Функция FreeAndNil не нарушена/устарела или что-то вроде этого, и это не повредит ваш код. Некоторые утверждают, что использование FreeAndNil может привести или указать недостаток дизайна.

Я использую FreeAndNil EVEN для локальной переменной. Использование его в локальной переменной кажется POINTLESS, так как переменная исчезает, как только вы выходите из процедуры. Однако это хорошая практика, которая будет стоить вам всего лишь нескольких лишних байтов. Подумайте, что позже вы можете добавить больше кода в конце процедуры, ПОСЛЕ того, где вы освободили объект, код, который (очевидно, случайно) попытается получить доступ к освобожденному объекту. Если объектом был NIL, BABUM, мгновенный AV (пример).
Примечание. Некоторые люди могут сказать, что они никогда не обращались к свободному объекту (в основном это означает, что они никогда не ошибаются), поэтому в этом случае им не нужен FreeAndNil. Ну, я не робот. Я ошибаюсь.

Некоторые консервативные люди могут сказать, что этот простой вызов будет растрачивать ресурсы ОЗУ и ЦП. Я никогда не скажу, что сохранение памяти/процессора плохое. Мне нравится доставлять небольшие/быстрые/монолитные приложения тоже! Но я не думаю, что удаление с помощью FreeAndNil будет тратить больше нескольких байтов и циклов процессора (буквально немного). Это не будет иметь особого значения в повседневной жизни, особенно если вы считаете, что один графический ресурс, такой как символ TButton или значок вашей программы, может занимать 50-300 КБ, а ваша программа может иметь десятки из них.

Pros
Мейсон Уилер уже указывает на статью, в которой показан метод «ленивого создания», который использует FreeAndNil, который мы использовали в один день: http://tech.turbu-rpg.com/106/delphi-memory-management-made-simple

Против
Аллен Бауэр показывает здесь пример того, как использовать FreeAndNil в случае CERTAIN (деструктор визуального компонента) и быть действительно плохим: http://blogs.embarcadero.com/abauer/2010/02/16/38916
Аллен утверждает, что FreeAndNil следует заменить лучшими методами. Например, с FastMM. Тем не менее, вот простой фрагмент кода, в котором FastMM терпит неудачу, в то время как FreeAndNil сохраняет день: http://codeverge.com/embarcadero.delphi.rtl/freeandnil-to-use-or-not-to-use/1067733

Поскольку есть оба аргумента pro и против FreeAndNil, вам решать, нравится это или нет.

Илон Маск рекомендует:  Что такое код filemtime

Правильная обработка освобождения ресурсов через try…finally в Delphi

Есть много разных вариантов как можно использовать конструкцию try. finally для освобождения ресурсов. Многие из них работают неверно в особых ситуациях. Рассмотрим несколько вариантов подробнее.

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

Прежде всего, установим ReportMemoryLeaksOnShutdown := True в dpr файле, для того чтобы отслеживать утечки памяти.

FreeAndNil — Процедура Delphi

129 просмотра

1 ответ

263 Репутация автора

Есть ли FreeAndNil (WaitForThread) также бесплатно TStringList создан здесь WaitForThread.CommandLineList: = TStringList.Create;

Ответы (1)

3 плюса

30176 Репутация автора

Имеет FreeAndNil(WaitForThread) также бесплатно TStringList здесь созданы WaitForThread.CommandLineList:=TStringList.Create;

FreeAndNil(WaitForThread) освободит только сам поток, а не любые объекты, созданные этим потоком.

Итак, ответ — нет, вам придется сделать это в деструкторе потока.

Обратите внимание, что если NumberOfWaitingThreads > 1, вы пропустите все объекты потока, кроме последнего. Исправьте это, объявив массив TWaitForThread :

Delphi – методы уничтожения объекта

Ниже перечислены методы освобождения объектов при ручном управлении памятью.

Destroy

В основе всего лежит virtual метод Destroy класса TObject

Пользуемся им, например так…

Free (с проверкой на nil)

Самый популярный способ, на мой взгляд

DisposeOf

Появился в XE4 и создан для совместимости

FreeAndNil

Не потокобезопасный (позволяет 2 потокам войти в деструктор экземпляра)

Не типобезопасный, данный код приведет к AV

Delphi Notes

Заметки Delphi + Oracle программиста

Страницы

среда, 22 мая 2020 г.

Как замена Free на FreeAndNil может поломать логику

Этот пост посвящается всем любителям споров FreeAndNil vs Free. Покажу пример, когда бездумную замену второго на первое делать нельзя.
Для понимания проблемы, покажу историю развития вопроса. Понятно, что если задачу решать полностью с нуля, то её можно решить разными способами, и можно выбрать решение, когда FreeAndNil будет лучшим и правильным вариантом. Однако в исторической перспективе получилось так, как получилось, я увидел что FreeAndNil всё поломает и решил об этом написать заметку.

Есть у меня один фрейм (TFrame), на который динамически в Run-Time создаётся компонет — превью отчёта. Т.к. превью — это наследник от TComponent, то я использую свойство Owner при создании и не забочусь об явном уничтожении превью. Создание дёргается внутри некоторого метода, который может быть вызван из вне несколько раз, выглядит это примерно так:
Соответственно уничтожение FfrxPreviewForm происходит автоматически при уничтожении фрейма; к экземпляру FfrxPreviewForm за пределами или в деструкторе фрейма я не обращаюсь, поэтому явно обнулять переменную нет необходимости.

В какой-то момент времени, мне понадобилось сохранять текущее состояние превью при выходе из приложения. Сделал я это просто:

В VCL это работает так: при уничтожении экземпляра фрейма, фрейм (как наследник от TComponent) перебирает все компоненты, которыми владеет, и уничтожает их. При этом компонент оповещает владельца о том, что сейчас будет уничтожен.
Чисто теоретически, SavePreviewOptions может стать публичным методом, поэтому в Notification я добавил очистку ссылки (хотя на текущий момент это не обязательно).

И вот настал момент, когда в методе SomeMethod понадобилась возможность уничтожить FfrxPreviewForm (с сохранением его состояния). Делаю я это примерно так:

Надеюсь Вы понимаете, что тут происходит.
А теперь пища для ума: что будет, если FfrxPreviewForm.Free заменить на FreeAndNil(FfrxPreviewForm)?

4 коммент.:

И что будет? Не вызовется деструктор и тем самым не уничтожатся компоненты во фрейме

Ну то есть FreeAndNil помог найти логическую проблему: обращение к компоненту в момент его удаления (читай: в переходном состоянии) ;)

Вы оба не правы. Вспомните о том, что FreeAndNil — он на самом деле работает как NilThenFree.
Т.е. при FreeAndNil(FfrxPreviewForm) сначала произойдёт установка переменной FfrxPreviewForm в nil, затем дёрнется деструктор превью, который дёрнет Notification. И вот в нём условие (AComponent = FfrxPreviewForm) не отработает, а значит и не вызовется SavePreviewOptions.

Т.е. утечек памяти не будет, но логика (когда при уничтожении превью надо сохранять его состояние) поломается. И такое не поддаётся диагностике.

Согласен с GunSmoker, надо изменять логику сохранения

FreeAndNil — Процедура Delphi

Как совершенно правильно писал Fuud, заnilять объект после Free иногда нужно, если потом нужно проверить ссылается ли переменная на корректный объект. Ну, например, знаем, что объект в ближайшее время не понадобится и, чтобы он память не жрал, хотим его уничтожить, тогда делаем ему Free и помещаем в него nil. Ну а потом можно проверить if Assigned(. если Assigned, то пользуем, иначе создаем. Ну, и тому подобные случаи.

Так вот, как написано в FM у Borland’a, FreeAndNil предоставляет более безопасный способ по-сравнению с конструкцией:

поскольку, если в obj.Free (читай — в obj.Destroy) возникнет какое-то исключение, то до строчки obj := nil мы не долетим, а так в obj у нас точно будет nil.

В принципе, этот FreeAndNil является аналогом конструкции:

И эта конструкция, кстати, более интуитивна понятна, чем какой-то там FreeAndNil, поэтому последнее время лично я предпочитаю писать именно так.

К тому же последняя конструкция более безопасна, ведь параметр у FreeAndNil — нетипизированный. Пример из жизни: как-то я случайно туда интерфейс передал — сначала это объект был, потом на интерфейсы переделал, запустил на компиляцию, мне компилятор все места показал, где использовался класс — я там на интерфейс поправил, а это место соответственно и компилятор, и я пропустили (какое единодушие :-) ) — все OK. Ну и как всегда, по закону подлости, exception не на этой строчке полетел, а совсем в другом месте, что стоило до-о-о-о-олгих часов общения с отладчиком.

Что предпочтительнее: Free или FreeAndNil?

Какова основная разница между свободной и FreeAndNil?

Является ли FreeAndNil = Free + Ноль?

Когда я должен использовать Free и когда я должен использовать FreeAndNil?

Я не получаю это, когда выпучив кто-то может мне помочь.

И посмотрим на реализацию:

Примеры

Рассмотрим следующий код:

Это создаст ошибку или недействительное (пустое) растровое изображение на рабочем столе, потому что я пытаюсь использовать объект , который был освобожден. Да, несмотря на то, bm был освобожден, он по — прежнему «присвоен», то есть по- bm прежнему указывает на адреса памяти, несмотря на то, что нет ничего (полезная) там. Чтобы преодолеть это, можно установить bm := nil , в качестве гарантии, тогда assigned(bm) вернет ложь, так как один хотел. Более или менее, FreeAndNil(bm) является сокращением bm.Free; bm := nil . Первое утверждение освобождает всю память (и OS ресурсов, процессорное время и т.д. , используемые объектом), и bm := nil устанавливает «указатель» bm на nil , так что bm больше не указывает на место , где объект не имел обыкновение быть, но больше не является. Таким образом , вы (и процедуры , как assigned ) не ведитесь поверить , что все еще есть растровый объект.

Илон Маск рекомендует:  Faq конференции ru php

обсуждение

Некоторые говорят , что вы всегда должны использовать FreeAndNil(foo) вместо foo.Free . А почему бы не? Дополнительные инструкции foo := nil , вероятно , не слишком много наносекунд , чтобы выполнить, и на самом деле assigned(foo) = false является очень хорошим свойством освобожденного объекта. Но опять же , если вы знаете , что вы делаете, и знайте , что вы никогда не будете использовать foo объект снова после освобождения его, то вы могли бы придерживаться только foo.free . На самом деле, некоторые утверждают , что во многих случаях (но не все), пытаясь использовать переменный освобожденный объект является ошибкой самого по себе. (Конечно , есть случаи , когда вы делаете это намеренно — у вас есть объект , foo который иногда назначается , а иногда нет.)

В основном, FreeAndNil устанавливает ссылку на ноль , а затем освобождает объект. Это помечает его как Unassigned. Поэтому единственная причина , вам нужно будет использовать FreeAndNil, если ваш код будет повторно использовать ссылку. Если вы находитесь в деструкторе или , наконец , блок, освобождая объекты , которые вы никогда не собираетесь снова прикоснуться, просто использовать Free.

См Управление памяти Delphi Made Simple для примера , когда я нашел его полезным. Комментарий Mghie в нижней также стоит читать.

Я отвечу по-другому.

Может быть, наполняя ссылку на объект с nil освободив ваш объект не всегда хорошая идея.

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

Таким образом, заполняя его с магическим числом (похоже на то , FastMM менеджер памяти может делать с содержимым блоков памяти , когда эти блоки освобождаются).

@Bharat, разница между Free и в FreeAndNil том , что в дополнение к свободной памяти , используемой объектом FreeAndNil задает ссылку на объект ноль.

Вы можете проверить тезисы ссылки для обсуждения использования Free или FreeAndNil

Даже если кажется, не будет сильно отличаться, чем Free, это поможет вам много позже во время охоты на ошибки кода.

Только подумайте, что произойдет, если вы не используете FreeAndNil, а затем где-то в вашем коде вы получаете доступ к освобожденному объекту. Если вы страшно повезло, программа зависнет, когда он бежит домой (да это крах «хорошим» аварии). Если вы немного не повезло, что произойдет сбой в компьютере клиента. Тогда реальная боль начинается!

Как и другие уже отмечалось, сама FreeAndNil не плохо. Функция FreeAndNil не сломана / устаревшая или что-то подобное, и это будет не повреждена ваш код. Некоторые утверждают, что, опираясь на FreeAndNil может привести или указать недостаток дизайна.

Я использую FreeAndNil даже на локальной переменной. С его помощью на локальной переменной кажется бессмысленным , так как переменная исчезает , как только вы выйти из процедуры. Тем не менее, это хорошая практика , которая будет стоить вам несколько лишних байт только. Подумайте , что вы можете позже добавить дополнительный код в конце процедуры, после того момент , когда вы освобожденный объект, код , который будет (очевидно , случайно) попытаться получить доступ к освобожденному объекту. Если объект был NIL, Бабум, растворимый AV ( пример ).
Примечание: Некоторые люди могут сказать , что они никогда не обращались свободный объект ( в основном это означает , что они никогда не делают ошибок) , поэтому они не нуждаются в FreeAndNil в этом случае. Ну, я не робот. Я делаю ошибки.

Некоторые консервативные люди могут сказать, что это просто вызов будет тратить RAM и ресурсы процессора. Я никогда не буду когда-нибудь сказать, что сохранение памяти / CPU плохо. Я хотел бы поставить небольшие / быстрые / монолитные приложения тоже! Но я не думаю, что удаление с помощью FreeAndNil будет тратить больше, чем несколько байт и циклов процессора (буквально несколько). Это не будет иметь реальное значение в жизни день за днем, особенно, когда вы думаете, что один графический ресурс, как глиф TButton или иконку вашей программы может занять 50-300KB, и ваша программа может иметь десятки их.

За
Mason Wheeler уже указывает на статью , которая показывает метод «ленивым создания» , который использует FreeAndNil , что все мы использовали один день: http://tech.turbu-rpg.com/106/delphi-memory-management-made-simple

Минусы
Allen Bauer здесь приведен пример о том , как с помощью FreeAndNil в одном случае (деструктор визуального компонента) и быть на самом деле плохо: http://blogs.embarcadero.com/abauer/2010/02/16/38916
Аллен утверждает , что FreeAndNil должны быть заменены более совершенными методами. Например , с FastMM. Однако, вот простой кусок кода , где FastMM терпит неудачу в то время как FreeAndNil экономит день: http://codeverge.com/embarcadero.delphi.rtl/freeandnil-to-use-or-not-to-use/1067733

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

Which is preferable: Free or FreeAndNil?

What is the basic difference between Free and FreeAndNil?

Is FreeAndNil = Free + Nil?

When should i use Free and when should i use FreeAndNil?

I am not getting these when goggling can someone help me.

Thanks in advance.

5 Answers 5

And have a look at the implementation:

Examples

Consider the following code:

This will create an error or an invalid (empty) bitmap on my desktop, because I try to use an object that has been freed. Yes, even though bm has been freed, it is still «assigned», i.e. bm still points to a memory adress, even though there is nothing (usable) there. To overcome this, one can set bm := nil , as a safeguard, Then assigned(bm) will return false, as one would want. More or less, FreeAndNil(bm) is a shorthand for bm.Free; bm := nil . The first statement frees all memory (and OS resources, CPU time etc. used by the object), and bm := nil sets the «pointer» bm to nil , so that bm no longer points to the place where the object used to be, but no longer is. This way you (and routines like assigned ) will not get fooled to believe that there still is a bitmap object.

Илон Маск рекомендует:  Что такое код posix_setsid

Discussion

Some say that you should always use FreeAndNil(foo) rather than foo.Free . Well, why not? The additional instruction foo := nil will probably not take too many nanoseconds to execute, and indeed assigned(foo) = false is a very nice property of a freed object. But then again, if you know what you are doing, and know that you will never use the foo object again after freeing it, then you could stick to just foo.free . Really, some would argue that in many cases (but not all), trying to use a variable of a freed object is a bug by itself. (Of course there are cases where you do this intentionally — you have an object foo that sometimes is assigned and sometimes is not.)

Basically, FreeAndNil sets the reference to nil and then frees the object. This marks it as unassigned. So the only reason you would need to use FreeAndNil is if your code is going to reuse the reference. If you’re in a destructor or a finally block, freeing objects that you’re never going to touch again, just use Free.

See Delphi Memory Management Made Simple for an example of when I did find it useful. Mghie’s comment at the bottom is also worth reading.

I’ll answer in a different way.

Maybe, filling your object reference with nil after freeing your object is not always a good idea.

That way, you do not have a distinction between a reference that was never used (and hence is nil ), and a reference that has been used, but should not be used in the future.

So, filling it with a magic number (similar to what the FastMM memory manager can do with the content of blocks of memory when those blocks are freed).

@Bharat, the difference between Free and FreeAndNil is that in addition to free memory used by an object FreeAndNil sets the object reference to nil.

you can check theses links for discussions about use Free or FreeAndNil

Even if doesn’t seem to be much different than Free, it will help you a lot later while hunting to bugs your code.

Just think what happens if you DON’T use FreeAndNil and then somewhere in your code you access a freed object. If you are terrible lucky, your program will crash when it runs home (yes that’s crash is a ‘good’ crash). If you are a bit unlucky it will crash in customer’s computer. Then the real pain starts!

As others already pointed, the FreeAndNil itself is not bad. The FreeAndNil function is not broken/obsolete or something like this and it will not corrupt your code. Some will argue that relying on FreeAndNil may lead or indicate a design flaw.

I use FreeAndNil EVEN on a local variable. Using it on a local variable seems POINTLESS since the variable vanishes as soon as you exit the procedure. However, it is good practice that will cost you few extra bytes only. Think that you may at a later date add more code at the end of the procedure, AFTER the point where you freed the object, code that will (obviously accidentally) try to access the freed object. If the object was NIL, BABUM, instant AV (example).
Note: Some people may say they never ever accessed a free object (basically meaning they never make mistakes) so they don’t need FreeAndNil in this case. Well, I am not a robot. I do mistakes.

Some conservative people may say this simple call will waste RAM and CPU resources. I will never ever say that conserving memory/CPU is bad. I like to deliver small/fast/monolithic applications too! But I don’t think that removing using FreeAndNil will waste more than few bytes and CPU cycles (literally few). It will not make a real difference in the day-by-day life, especially when you think that a single graphic resource like a TButton glyph or your program’s icon can take 50-300KB, and your program can have dozens of these.

Pros
Mason Wheeler already points to a article that shows the ‘lazy creation’ method that uses FreeAndNil that we all used one day: http://tech.turbu-rpg.com/106/delphi-memory-management-made-simple

Cons
Allen Bauer HAD an article suggesting that using the FreeAndNil in the a CERTAIN case (destructor of a visual component) could be bad: http://blogs.embarcadero.com/abauer/2010/02/16/38916
Allen states that FreeAndNil should be replaced with better methods. For example with FastMM. However, here is a simple piece of code where FastMM fails while FreeAndNil saves the day: http://codeverge.com/embarcadero.delphi.rtl/freeandnil-to-use-or-not-to-use/1067733
BUT Embarcadero decided to delete that article so something must have been wrong with it.

As a conclusion, at this moment, we don’t have a single piece of CONCRETE (and compilable) code to show that FreeAndNil could do harm. (For those that are against FreeAndNil please enlighten us, by posting the code).
However, we de do have code that shows how FreeAndNil can save our ass.

Процедура FreeAndNil также освобождает TStringList, созданный в потоке?

FreeAndNil (WaitForThread) также освобождает TStringList, созданный здесь WaitForThread.CommandLineList: = TStringList.Create;

FreeAndNil(WaitForThread) также освобождает TStringList созданный здесь WaitForThread.CommandLineList:=TStringList.Create;

FreeAndNil(WaitForThread) освободит сам поток, а не объекты, созданные потоком.

Итак, ответ — нет, вам придется это сделать в деструкторе потока.

Обратите внимание, что если NumberOfWaitingThreads > 1, вы NumberOfWaitingThreads все объекты потока, кроме последнего. Исправьте это, объявив массив TWaitForThread :

Процедура FreeAndNil также освобождает TStringList, созданный в потоке?

Создает ли FreeAndNil (WaitForThread) бесплатный TStringList, созданный здесь WaitForThread.CommandLineList: = TStringList.Create;

1 ответ

FreeAndNil(WaitForThread) также бесплатно TStringList созданный здесь WaitForThread.CommandLineList:=TStringList.Create;

FreeAndNil(WaitForThread) освободит только сам поток, а не любые объекты, созданные этим потоком.

Таким образом, ответ — нет, вам придется сделать это в деструкторе потока.

Обратите внимание, что если NumberOfWaitingThreads > 1, вы потеряете все объекты потока, кроме последнего. Исправьте это, объявив массив TWaitForThread :

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL