Класс потока в Delphi
Раптор [Ментальная студия]
http://mental.mentsu.com
третий
Поговорив о конструкторе, давайте посмотрим на деструктор:
деструктор TThread.Destroy;
начинать
если (FThreadID <> 0) и не FFinished, то
начинать
Прекратить;
если FCreateSuspended, то
Резюме;
Ожидание;
конец;
если FHandle <> 0, то CloseHandle(FHandle);
унаследовал Уничтожить;
FFatalException.Бесплатно;
УдалитьТред;
конец;
Прежде чем освободить объект потока, сначала проверьте, выполняется ли поток. Если поток все еще выполняется (идентификатор потока не равен 0 и флаг завершения потока не установлен), для завершения потока вызывается процесс Terminate. Процесс Terminate просто устанавливает флаг Terminate класса потока, как показано в следующем коде:
ПРОЦЕДУРА TThread.Terminate;
начинать
FTerminate := Истина;
конец;
Следовательно, поток должен продолжать выполняться до тех пор, пока не завершится нормально, вместо немедленного завершения потока. Это следует отметить.
Небольшое отступление: многие люди спрашивали меня, как «немедленно» завершить поток (конечно, имея в виду потоки, созданные с помощью TThread). Конечно, это не работает! Единственный способ завершить поток — позволить методу Execute завершить выполнение, поэтому, вообще говоря, если вы хотите, чтобы ваш поток завершился как можно скорее, вы должны постоянно проверять флаг Termination в методе Execute в течение короткого периода времени, чтобы что вы сможете выйти вовремя. Это очень важный принцип при разработке многопоточного кода!
Конечно, если вам необходимо иметь возможность выйти из потока «немедленно», то класс TThread не является хорошим выбором, потому что, если вы используете API для принудительного завершения потока, объект потока TThread в конечном итоге не будет освобожден правильно, и Нарушение доступа произойдет при разрушении объекта. В этом случае для создания потоков вы можете использовать только функции API или RTL.
Если поток находится в состоянии приостановки запуска, переведите поток в рабочее состояние, а затем вызовите WaitFor для ожидания. Его функция — дождаться завершения потока, прежде чем продолжить выполнение. Реализация WaitFor будет объяснена позже.
После завершения потока закройте дескриптор потока (дескриптор существует при обычном создании потока) и освободите объект потока, созданный операционной системой.
Затем вызовите TObject.Destroy, чтобы освободить этот объект и перехваченный объект исключения, и, наконец, вызовите RemoveThread, чтобы уменьшить количество потоков в процессе.
Другие аспекты, касающиеся приостановки/возобновления и настроек приоритета потоков, не являются предметом внимания этой статьи и не будут обсуждаться снова. Ниже будут обсуждаться два других направления этой статьи: Synchronize и WaitFor.
Но прежде чем представить эти две функции, необходимо представить две другие технологии синхронизации потоков: события и критические секции.
События отличаются от событий в Delphi. По сути, Event эквивалентно глобальной логической переменной. Он имеет две операции присваивания: Set и Reset, которые эквивалентны установке значения True или False. А проверка его значения осуществляется посредством операции WaitFor. В соответствии с платформой Windows существует три функции API: SetEvent, ResetEvent и WaitForSingleObject (существует несколько API, реализующих функцию WaitFor, это самый простой).
Эти три элемента являются примитивами, поэтому Event может реализовывать приложения в многопоточном режиме, чего не могут сделать обычные логические переменные. Функции Set и Reset уже упоминались ранее. Теперь поговорим о функции WaitFor:
Функция WaitFor заключается в проверке того, является ли состояние события состоянием Set (эквивалентно True), оно немедленно возвращается. Если нет, оно ожидает изменения состояния Set в течение периода ожидания. поток, вызывающий WaitFor, находится в приостановленном состоянии. Кроме того, в WaitFor есть параметр для установки времени ожидания. Если этот параметр равен 0, он не ожидает и немедленно возвращает статус события. Если он равен INFINITE, он ждет бесконечно, пока не возникнет статус Set. Если это ограниченное значение, оно будет. ждет соответствующее количество миллисекунд. Затем возвращает статус события.
Когда событие переходит из состояния Reset в состояние Set, оно пробуждает другие потоки, приостановленные из-за события WaitFor. Вот почему оно называется Event. Так называемое «событие» относится к «переходу состояния». Эта информация о «переходе состояния» может передаваться между потоками через события.
Конечно, аналогичную функцию можно также реализовать с помощью защищенной (см. введение в критический раздел ниже) логической переменной, если WaitFor заменяется циклом кода, проверяющим логическое значение. Функционально проблем нет, но при реальном использовании вы обнаружите, что такое ожидание будет занимать много ресурсов ЦП, снижать производительность системы и влиять на скорость выполнения других потоков, поэтому это неэкономично, а иногда даже возможно. проблемы. Поэтому не рекомендуется использовать его таким образом.
(продолжение следует)