Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка 2.doc
Скачиваний:
18
Добавлен:
13.02.2015
Размер:
1.23 Mб
Скачать
  1. Завершение потока

Поток можно завершит четырьмя способами:

  1. Функция потока возвращает управление.

Функция потока, возвращая управление, гарантирует корректную очистку всех ресурсов, принадлежащих данному потоку. При этом:

  • любые С++ объекты, созданные данным потоком, уничтожаются соответствующими деструкторами;

  • система корректно освобождает память, которую занимал стек потока;

  • система устанавливает код завершения данного потока. Его функция и возвращает;

  • счетчик пользователей данного объекта ядра (поток) уменьшается на 1.

  1. Поток самоуничтожается вызовом функции ExitThread.

При желании немедленно завершить поток изнутри используют функцию ExitThread(DWORD dwExitCode).

При этом освобождаются все ресурсы ОС, выделенные данному потоку, но С С++ ресурсы (например, объекты классов С++) не очищаются. Именно поэтому не рекомендовано завершать поток, используя эту функцию.

Если же вы ее использовали, то кодом возврата потока будет тот параметр, который вы передадите в данную функцию.

Функция ExitThread заканчивает работу потока.

Синтаксис

VOID ExitThread(

DWORD dwExitCode // код выхода для этого потока

);

Параметры

dwExitCode – определяет код выхода для вызывающего потока. Используйте функцию GetExitCodeThread, чтобы получить код выхода из потока.

Возвращаемые значения

У этой функции нет возвращаемого значения.

ExitThread – предпочтительный метод завершения работы потока. Когда эта функция вызывается (или явно или при помощи возврата из процедуры потока), стек текущего потока освобождается, а поток завершает работу. Функция точки входа всех связанных динамически подключаемых библиотек (DLL) вызывается со значением, указывающим, что поток отключается от DLL.

Если поток является последним потоком в процессе, когда эта функция вызвана, процесс потока также завершает работу.

Состояние объекта потока становится сигнальным, освобождая любые другие потоки, которые ждали, когда поток закончит работу. Состояние завершения потока изменяется от STILL_ACTIVE до значения параметра dwExitCode.

Завершение потока необязательно удаляет объект потока из операционной системы. Объект потока удаляется, когда закрывается последний дескриптор потока.

  1. Другой поток процесса вызывает функцию TerminateThread.

Если появилась необходимость уничтожить поток снаружи, то это моет сделать функция TeminateThread.

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

При завершении процесса происходит следующее.

Завершение потока происходит принудительно. Деструкторы объектов не вызываются, и т.д. и т.д.

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

Функция TerminateThread завершает работу потока.

Синтаксис

BOOL TerminateThread(

HANDLE hThread, // дескриптор потока

DWORD dwExitCode // код завершения для потока

);

Параметры

hThread – дескриптор потока, который завершает работу. В Windows NT/2000/XP дескриптор должен иметь право доступа THREAD_TERMINATE.

dwExitCode – код завершения работы потока. Чтобы получать дополнительные информацию об ошибке необходимо вызвать функцию GetLastError.

Возвращаемые значения

Если функция завершается успешно, величина возвращаемого значения - не ноль. Если функция завершается с ошибкой, величина возвращаемого значения - ноль. Чтобы получать дополнительные информацию об ошибке необходимо вызвать функцию GetLastError.

Функция TerminateThread – используется для того, чтобы заставить поток завершить работу. Когда это происходит, у целевого потока нет возможности, чтобы исполнить какой-либо код непривилегированного (пользовательского) режима, и его исходный стек не освобождается. Динамически подключаемые библиотеки (DLL), связанные с потоком не уведомляются о том, что поток завершает работу.

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

  • Если целевой поток владеет критической секцией программы, критическая секция не будет освобождена.

  • Если целевой поток выделяет память из "кучи ", блокировка "кучи " не будет освобождена.

  • Если целевой поток, когда он завершает работу, вызывает на выполнение некоторый код kernel32, состояние kernel32 для процесса потока может быть несовместимым.

  • Если целевой поток управляет, глобальным состоянием совместно используемых DLL, состояние DLL может быть разрушено, воздействиями других пользователей DLL.

Поток не может защитить себя против TerminateThread, не иначе как управляя доступом к своим дескрипторам. Дескриптор потока, возвращенный функциями CreateThreadиCreateProcess, имеет доступTHREAD_TERMINATE, так что любая вызывающая программа, удерживающая один из этих дескрипторов может завершить работу вашего потока.

Состояние объекта потока становится сигнальным, освобождая любые другие потоки, которые ждали завершения работы потока. Состояние завершения потока изменяется от STILL_ACTIVE до значения параметра dwExitCode.

Завершение работы потока необязательно удаляет объект потока из системы. Объект потока удаляется тогда, когда закрывается последний дескриптор потока.

  1. Завершается процесс, содержащий данный поток. Для этого используют функцию ExitProcess.

Функции ExitProcess, ExitThread,CreateThread,CreateRemoteThreadи процесс, который запущен (как результат вызоваCreateProcess), в пределах процесса переводятся между собой в последовательный режим. Одновременно в адресном пространстве может происходить только одно из этих событий. Это означает нижеследующие ограничения выполнения:

  • В ходе запуска процесса и процедуры инициализации DLL, новые потоки могут быть созданы, но они не начинают исполнение кода до тех пор, пока не будет сделана инициализация DLL для процесса.

  • Одновременно только один поток в процессе может быть инициализирован или отключен процедурой в DLL.

  • Функция ExitProcess не возвращает значения до тех пор, пока в потоках не отработают в их DLL процедуры инициализации или отключения.

Поток, который использует функции C библиотеки периода исполнения, должен использовать C - функции периода исполнения _beginthread и _endthread для управления потоком, а не CreateThread и ExitThread. Кто поступает таким образом, то приводит к сбою программу, когда вызывается ExitThread, из-за того, что происходит утечка ресурсов в области памяти.

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

Таблица №1