Лекция 4
Поток(thread) определяет последовательность исполнения кода в процессе.
При инициализации процесса система всегда создает первичный поток. Большинство приложений обходятся одним потоком, однако, процессы могут создавать множество потоков. Это позволяет добиться минимального простоя процессора и тем самым увеличить эффективность работы.
Примеры: проверка правописания в текстовом редакторе; выполнение расчетов на нескольких процессорах; моделирование поведения систем, состоящих из независимых элементов.
Для порождения нового потока используется функция
function CreateThread(lpThreadAttributes: Pointer;
dwStackSize: DWORD;
lpStartAddress: TFNThreadStartRoutine;
lpParameter: Pointer;
dwCreationFlags: DWORD;
var lpThreadId: DWORD
):THandle;
Функция создает объект ядра - поток и все его структуры, создает стек потока и запускает его на выполнение (не всегда) .При удачном создании потока функция вернет его описатель, иначе 0. Код ошибки можно узнать, вызвав функцию function GetLastError.
lpThreadAttributes - атрибуты защиты для потока.
dwStackSize - определяет часть адресного пространства, отводимого под стек. Если вы обнулили этот параметр, то размер стека будет найден в коде приложения (компоновщик позволяет управлять размером стека для приложения). По умолчанию 1 Мб.
lpStartAddress - определяет адрес стартовой функции потока. Функция должна иметь вид function …( lpParameter :pointer):integer; Параметр lpParameter идентичен параметру lpParameter передаваемому в CreateThread. По сути функция создания потока передает этот параметр по эстафете стартовой функции потока. В данной функции должен содержаться весь код потока, так как по ее завершению, поток будет завершен.
dwCreationFlags - определяет дополнительные флаги, управляющие созданием потока.0-поток начинает выполняться немедленно, CREATE_SUSPENDED - поток приостанавливает свое выполнение до дальнейших указаний.
lpThreadId - возвращаемый идентификатор потока
Пример:
var
hObjThread :THandle;
function StartThread(Param :pointer):integer;
begin
ShowMessage('Поток создан'+#13+
'Псевдоописатель $'+IntToHex(GetCurrentThread,32)+#13+
'ID потока $'+IntToHex(GetCurrentThreadId,32));
// что то делаем
end;
procedure TForm1.Button1Click(Sender: TObject);
var ThreadId: DWORD;
begin
hObjThread:=CreateThread(nil,0, @StartThread, nil, 0, ThreadId);
if hObjThread=0 then
raise Exception.Create(SysErrorMessage(GetLastError));
LabelThreadHandle.Caption:='Описатель потока $'+IntToHex(hObjThread,32);
LabelThreadID.Caption:='ID потока $'+IntToHex(integer(ThreadId),32);
end;
Корректнее использовать BeginThread из библиотеки Delphi, которая устанавливает фрейм исключения, разрешая ОС обработать исключения, которые возникают внутри стартовой функции потока.
Несколько полезных функций, относящихся к потоку.
function GetThreadTimes(hThread: THandle; var lpCreationTime, lpExitTime, lpKernelTime, lpUserTime: TFileTime): BOOL; - возвращает время, затраченное на выполнение потока. Параметры: lpCreationTime - время создания потока, lpExitTime - время завершения потока, lpKernelTime - время затраченное на выполнение кода ядра, lpUserTime - время затраченное на выполнение кода потока. (Только в Windows NT)
Завершить поток можно тремя способами
потоков вызывает функцию procedure ExitThread(dwExitCode: DWORD); dwExitCode - код возврата.
Поток процесса вызывает function TerminateThread(hThread: THandle; dwExitCode: DWORD): BOOL;
Процесс, содержащий данный поток завершается.